home *** CD-ROM | disk | FTP | other *** search
/ MacHome 2001 January / MacHome Magazine Demo Disc January 2001.iso / mac / Software / Applications / Squeak app design envir. ….sea / Squeak app design envir. 2.8 / Squeak2.8.changes < prev    next >
Encoding:
Text File  |  2000-08-22  |  9.4 MB  |  20 lines  |  [STch/FAST]

Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
  1. 'From Squeak2.8 of 13 June 2000 [latest update: #2356] on 16 August 2000 at 7:43:20 pm'!
  2.  
  3. This is a simple ADPCM (adapative delta pulse code modulation) codec. This is a general audio codec that compresses speech, music, or sound effects equally well, and works at any sampling rate (i.e., it contains no frequency-sensitive filters). It compresses 16-bit sample data down to 5, 4, 3, or 2 bits per sample, with lower fidelity and increased noise at the lowest bit rates. Although it does not deliver state-of-the-art compressions, the alorithm is small, simple, and extremely fast, since the encode/decode primitives have been translated into C primitives.
  4.  
  5. This codec will also encode and decode all Flash .swf file compressed sound formats, both mono and stereo. (Note: stereo Flash compression is not yet implemented, but stereo decompression works.)
  6. !
  7. !ADPCMCodec methodsFor: 'bit streaming' stamp: 'jm 3/28/1999 16:24'!
  8. nextBits: n
  9.     "Answer the next n bits of my bit stream as an unsigned integer."
  10.  
  11.     | result remaining shift |
  12.     self inline: true.
  13.  
  14.     result _ 0.
  15.     remaining _ n.
  16.     [true] whileTrue: [
  17.         shift _ remaining - bitPosition.
  18.         result _ result + (currentByte bitShift: shift).
  19.         shift > 0
  20.             ifTrue: [  "consumed currentByte buffer; fetch next byte"
  21.                 remaining _ remaining - bitPosition.            
  22.                 currentByte _ (encodedBytes at: (byteIndex _ byteIndex + 1)).
  23.                 bitPosition _ 8]
  24.             ifFalse: [  "still some bits left in currentByte buffer"
  25.                 bitPosition _ bitPosition - remaining.
  26.                 "mask out the consumed bits:"
  27.                 currentByte _ currentByte bitAnd: (255 bitShift: (bitPosition - 8)).
  28.                 ^ result]].
  29. ! !
  30.  
  31. !ADPCMCodec methodsFor: 'bit streaming' stamp: 'jm 3/28/1999 20:21'!
  32. nextBits: n put: anInteger
  33.     "Write the next n bits to my bit stream."
  34.  
  35.     | buf bufBits bitsAvailable shift |
  36.     self inline: true.
  37.  
  38.     buf _ anInteger.
  39.     bufBits _ n.
  40.     [true] whileTrue: [
  41.         bitsAvailable _ 8 - bitPosition.
  42.         shift _ bitsAvailable - bufBits.  "either left or right shift"
  43.         "append high bits of buf to end of currentByte:"
  44.         currentByte _ currentByte + (buf bitShift: shift).
  45.         shift < 0
  46.             ifTrue: [  "currentByte buffer filled; output it"
  47.                 encodedBytes at: (byteIndex _ byteIndex + 1) put: currentByte.
  48.                 bitPosition _ 0.
  49.                 currentByte _ 0.
  50.                 "clear saved high bits of buf:"
  51.                 buf _ buf bitAnd: (1 bitShift: 0 - shift) - 1.
  52.                 bufBits _ bufBits - bitsAvailable]
  53.             ifFalse: [  "still some bits available in currentByte buffer"
  54.                 bitPosition _ bitPosition + bufBits.
  55.                 ^ self]].
  56. ! !
  57.  
  58. !ADPCMCodec methodsFor: 'codec stuff' stamp: 'jm 3/27/1999 11:21'!
  59. bytesPerEncodedFrame
  60.     "Answer the number of bytes required to hold one frame of compressed sound data."
  61.     "Note: When used as a normal codec, the frame size is always 8 samples which results in (8 * bitsPerSample) / 8 = bitsPerSample bytes."
  62.  
  63.     ^ bitsPerSample
  64. ! !
  65.  
  66. !ADPCMCodec methodsFor: 'codec stuff' stamp: 'jm 7/2/1999 13:29'!
  67. compressAndDecompress: aSound
  68.     "Compress and decompress the given sound. Overridden to use same bits per sample for both compressing and decompressing."
  69.  
  70.     | compressed decoder |
  71.     compressed _ self compressSound: aSound.
  72.     decoder _ self class new
  73.         initializeForBitsPerSample: bitsPerSample
  74.         samplesPerFrame: 0.
  75.     ^ decoder decompressSound: compressed
  76.  
  77. ! !
  78.  
  79. !ADPCMCodec methodsFor: 'codec stuff' stamp: 'jm 3/28/1999 15:37'!
  80. decodeFrames: frameCount from: srcByteArray at: srcIndex into: dstSoundBuffer at: dstIndex
  81.     "Decode the given number of monophonic frames starting at the given index in the given ByteArray of compressed sound data and storing the decoded samples into the given SoundBuffer starting at the given destination index. Answer a pair containing the number of bytes of compressed data consumed and the number of decompressed samples produced."
  82.     "Note: Assume that the sender has ensured that the given number of frames will not exhaust either the source or destination buffers."
  83.  
  84.     encodedBytes _ srcByteArray.
  85.     byteIndex _ srcIndex - 1.
  86.     bitPosition _ 0.
  87.     currentByte _ 0.
  88.     samples _ dstSoundBuffer.
  89.     sampleIndex _ dstIndex - 1.
  90.     self privateDecodeMono: (frameCount * self samplesPerFrame).
  91.     ^ Array with: (byteIndex - (srcIndex - 1)) with: (sampleIndex - (dstIndex - 1))
  92. ! !
  93.  
  94. !ADPCMCodec methodsFor: 'codec stuff' stamp: 'jm 3/28/1999 15:28'!
  95. encodeFrames: frameCount from: srcSoundBuffer at: srcIndex into: dstByteArray at: dstIndex
  96.     "Encode the given number of frames starting at the given index in the given monophonic SoundBuffer and storing the encoded sound data into the given ByteArray starting at the given destination index. Encode only as many complete frames as will fit into the destination. Answer a pair containing the number of samples consumed and the number of bytes of compressed data produced."
  97.     "Note: Assume that the sender has ensured that the given number of frames will not exhaust either the source or destination buffers."
  98.  
  99.     samples _ srcSoundBuffer.
  100.     sampleIndex _ srcIndex - 1.
  101.     encodedBytes _ dstByteArray.
  102.     byteIndex _ dstIndex - 1.
  103.     bitPosition _ 0.
  104.     currentByte _ 0.
  105.     self privateEncodeMono: (frameCount * self samplesPerFrame).
  106.     ^ Array with: frameCount with: (byteIndex - (dstIndex - 1))
  107. ! !
  108.  
  109. !ADPCMCodec methodsFor: 'codec stuff' stamp: 'jm 3/28/1999 20:12'!
  110. resetForMono
  111.     "Reset my encoding and decoding state for mono."
  112.  
  113.     predicted _ 0.
  114.     index _ 0.
  115. ! !
  116.  
  117. !ADPCMCodec methodsFor: 'codec stuff' stamp: 'jm 3/28/1999 20:12'!
  118. resetForStereo
  119.     "Reset my encoding and decoding state for stereo."
  120.  
  121.     "keep state as SoundBuffers to allow fast access from primitive"
  122.     predicted _ SoundBuffer new: 2.
  123.     index _ SoundBuffer new: 2.
  124. ! !
  125.  
  126. !ADPCMCodec methodsFor: 'codec stuff' stamp: 'jm 3/27/1999 08:34'!
  127. samplesPerFrame
  128.     "Answer the number of sound samples per compression frame."
  129.  
  130.     frameSizeMask > 0 ifTrue: [^ frameSizeMask + 1].
  131.     ^ 8  "frame size when there are no running headers"
  132. ! !
  133.  
  134. !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'jm 3/28/1999 06:26'!
  135. decode: aByteArray bitsPerSample: bits
  136.  
  137.     ^ self
  138.         decode: aByteArray
  139.         sampleCount: (aByteArray size * 8) // bits
  140.         bitsPerSample: bits
  141.         frameSize: 0
  142.         stereo: false
  143. ! !
  144.  
  145. !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'jm 3/28/1999 15:57'!
  146. decode: aByteArray sampleCount: count bitsPerSample: bits frameSize: frameSize stereo: stereoFlag
  147.  
  148.     self initializeForBitsPerSample: bits samplesPerFrame: frameSize.
  149.     encodedBytes _ aByteArray.
  150.     byteIndex _ 0.
  151.     bitPosition _ 0.
  152.     currentByte _ 0.
  153.     stereoFlag
  154.         ifTrue: [
  155.             self resetForStereo.
  156.             samples _ SoundBuffer newMonoSampleCount: count.
  157.             rightSamples _ SoundBuffer newMonoSampleCount: count.
  158.             sampleIndex _ 0.
  159.             self privateDecodeStereo: count.
  160.             ^ Array with: samples with: rightSamples]
  161.         ifFalse: [
  162.             samples _ SoundBuffer newMonoSampleCount: count.
  163.             sampleIndex _ 0.
  164.             self privateDecodeMono: count.
  165.             ^ samples]
  166. ! !
  167.  
  168. !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'jm 3/30/1999 08:56'!
  169. decodeFlash: aByteArray sampleCount: sampleCount stereo: stereoFlag
  170.  
  171.     | bits |
  172.     encodedBytes _ aByteArray.
  173.     byteIndex _ 0.
  174.     bitPosition _ 0.
  175.     currentByte _ 0.
  176.     bits _ 2 + (self nextBits: 2).  "bits per sample"
  177.     self initializeForBitsPerSample: bits samplesPerFrame: 4096.
  178.     stereoFlag
  179.         ifTrue: [
  180.             self resetForStereo.
  181.             samples _ SoundBuffer newMonoSampleCount: sampleCount.
  182.             rightSamples _ SoundBuffer newMonoSampleCount: sampleCount.
  183.             sampleIndex _ 0.
  184.             self privateDecodeStereo: sampleCount.
  185.             ^ Array with: samples with: rightSamples]
  186.         ifFalse: [
  187.             samples _ SoundBuffer newMonoSampleCount: sampleCount.
  188.             sampleIndex _ 0.
  189.             self privateDecodeMono: sampleCount.
  190.             ^ Array with: samples].
  191. ! !
  192.  
  193. !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'jm 3/28/1999 08:59'!
  194. encode: aSoundBuffer bitsPerSample: bits
  195.  
  196.     ^ self
  197.         encodeLeft: aSoundBuffer
  198.         right: nil
  199.         bitsPerSample: bits
  200.         frameSize: 0
  201.         forFlash: false
  202. ! !
  203.  
  204. !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'jm 3/28/1999 08:58'!
  205. encodeFlashLeft: leftSoundBuffer right: rightSoundBuffer bitsPerSample: bits
  206.  
  207.     ^ self
  208.         encodeLeft: leftSoundBuffer
  209.         right: rightSoundBuffer
  210.         bitsPerSample: bits
  211.         frameSize: 4096
  212.         forFlash: true
  213. ! !
  214.  
  215. !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'jm 3/28/1999 09:17'!
  216. encodeLeft: leftSoundBuffer right: rightSoundBuffer bitsPerSample: bits frameSize: frameSize forFlash: flashFlag
  217.  
  218.     | stereoFlag sampleCount sampleBitCount bitCount |
  219.     self initializeForBitsPerSample: bits samplesPerFrame: frameSize.
  220.     stereoFlag _ rightSoundBuffer notNil.
  221.     sampleCount _ leftSoundBuffer monoSampleCount.
  222.     stereoFlag
  223.         ifTrue: [sampleBitCount _ 2 * (sampleCount * bitsPerSample)]
  224.         ifFalse: [sampleBitCount _ sampleCount * bitsPerSample].
  225.     bitCount _ sampleBitCount +
  226.         (self headerBitsForSampleCount: sampleCount stereoFlag: stereoFlag).
  227.  
  228.     encodedBytes _ ByteArray new: (bitCount / 8) ceiling.
  229.     byteIndex _ 0.
  230.     bitPosition _ 0.
  231.     currentByte _ 0.
  232.     flashFlag ifTrue: [self nextBits: 2 put: bits - 2].
  233.     stereoFlag
  234.         ifTrue: [
  235.             samples _ Array with: leftSoundBuffer with: rightSoundBuffer.
  236.             sampleIndex _ Array with: 0 with: 0.
  237.             self privateEncodeStereo: sampleCount]
  238.         ifFalse: [
  239.             samples _ leftSoundBuffer.
  240.             sampleIndex _ 0.
  241.             self privateEncodeMono: sampleCount].
  242.  
  243.     ^ encodedBytes
  244. ! !
  245.  
  246. !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'jm 3/27/1999 12:14'!
  247. headerBitsForSampleCount: sampleCount stereoFlag: stereoFlag
  248.     "Answer the number of extra header bits required for the given number of samples. This will be zero if I am not using frame headers."
  249.  
  250.     | frameCount bitsPerHeader |
  251.     frameSizeMask = 0 ifTrue: [^ 0].
  252.     frameCount _ (sampleCount / self samplesPerFrame) ceiling.
  253.     bitsPerHeader _ 16 + 6.
  254.     stereoFlag ifTrue: [bitsPerHeader _ 2 * bitsPerHeader].
  255.     ^ frameCount * bitsPerHeader
  256. ! !
  257.  
  258. !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'jm 3/28/1999 16:08'!
  259. indexForDeltaFrom: thisSample to: nextSample
  260.     "Answer the best index to use for the difference between the given samples."
  261.     "Details: Scan stepSizeTable for the first entry >= the absolute value of the difference between sample values. Since indexes are zero-based, the index used during decoding will be the one in the following stepSizeTable entry. Since the index field of a Flash frame header is only six bits, the maximum index value is 63."
  262.     "Note: Since there does not appear to be any documentation of how Flash acutally computes the indices used in its frame headers, this algorithm was guessed by reverse-engineering the Flash ADPCM decoder."
  263.  
  264.     | diff bestIndex |
  265.     self inline: true.
  266.  
  267.     diff _ nextSample - thisSample.
  268.     diff < 0 ifTrue: [diff _ 0 - diff].
  269.     bestIndex _ 63.
  270.     1 to: 62 do: [:j |
  271.         bestIndex = 63 ifTrue: [
  272.             (stepSizeTable at: j) >= diff ifTrue: [bestIndex _ j]]].
  273.     ^ bestIndex
  274. ! !
  275.  
  276. !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'jm 3/28/1999 20:48'!
  277. initializeForBitsPerSample: sampleBits samplesPerFrame: frameSize
  278.  
  279.     self resetForMono.
  280.     stepSizeTable _ #(7 8 9 10 11 12 13 14 16 17 19 21 23 25 28 31 34 37 41 45 50 55 60 66 73 80 88 97 107 118 130 143 157 173 190 209 230 253 279 307 337 371 408 449 494 544 598 658 724 796 876 963 1060 1166 1282 1411 1552 1707 1878 2066 2272 2499 2749 3024 3327 3660 4026 4428 4871 5358 5894 6484 7132 7845 8630 9493 10442 11487 12635 13899 15289 16818 18500 20350 22385 24623 27086 29794 32767).
  281.  
  282.     indexTable _ nil.
  283.     sampleBits = 2 ifTrue: [
  284.         indexTable _ #(-1 2)].
  285.     sampleBits = 3 ifTrue: [
  286.         indexTable _ #(-1 -1 2 4)].
  287.     sampleBits = 4 ifTrue: [
  288.         indexTable _ #(-1 -1 -1 -1 2 4 6 8)].
  289.     sampleBits = 5 ifTrue: [
  290.         indexTable _ #(-1 -1 -1 -1 -1 -1 -1 -1 1 2 4 6 8 10 13 16)].
  291.     indexTable ifNil: [self error: 'unimplemented bits/sample'].
  292.  
  293.     bitsPerSample _ sampleBits.
  294.     deltaSignMask _ 1 bitShift: bitsPerSample - 1.
  295.     deltaValueMask _ deltaSignMask - 1.
  296.     deltaValueHighBit _ deltaSignMask / 2.
  297.  
  298.     frameSize <= 1
  299.         ifTrue: [frameSizeMask _ 0]
  300.         ifFalse: [
  301.             (frameSize = (1 bitShift: frameSize highBit - 1))
  302.                 ifFalse: [self error: 'frameSize must be a power of two'].
  303.             frameSizeMask _ frameSize - 1].
  304.  
  305.     "keep as SoundBuffer to allow fast access from primitive"
  306.     indexTable _ SoundBuffer fromArray: indexTable.
  307.     stepSizeTable _ SoundBuffer fromArray: stepSizeTable.
  308. ! !
  309.  
  310. !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'jm 3/29/1999 07:13'!
  311. privateDecodeMono: count
  312.  
  313.     | delta step predictedDelta bit |
  314.     <primitive: 550>
  315.     self var: #stepSizeTable declareC: 'short int *stepSizeTable'.
  316.     self var: #indexTable declareC: 'short int *indexTable'.
  317.     self var: #samples declareC: 'short int *samples'.
  318.     self var: #encodedBytes declareC: 'unsigned char *encodedBytes'.
  319.  
  320.     1 to: count do: [:i |
  321.         (i bitAnd: frameSizeMask) = 1
  322.             ifTrue: [  "start of frame; read frame header"
  323.                 predicted _ self nextBits: 16.
  324.                 predicted > 32767 ifTrue: [predicted _ predicted - 65536].
  325.                 index _ self nextBits: 6.
  326.                 samples at: (sampleIndex _ sampleIndex + 1) put: predicted]
  327.             ifFalse: [
  328.                 delta _ self nextBits: bitsPerSample.
  329.                 step _ stepSizeTable at: index + 1.
  330.                 predictedDelta _ 0.
  331.                 bit _ deltaValueHighBit.
  332.                 [bit > 0] whileTrue: [
  333.                     (delta bitAnd: bit) > 0 ifTrue: [predictedDelta _ predictedDelta + step].
  334.                     step _ step bitShift: -1.
  335.                     bit _ bit bitShift: -1].
  336.                 predictedDelta _ predictedDelta + step.
  337.  
  338.                 (delta bitAnd: deltaSignMask) > 0
  339.                     ifTrue: [predicted _ predicted - predictedDelta]
  340.                     ifFalse: [predicted _ predicted + predictedDelta].
  341.                 predicted > 32767
  342.                     ifTrue: [predicted _ 32767]
  343.                     ifFalse: [predicted < -32768 ifTrue: [predicted _ -32768]].
  344.  
  345.                 index _ index + (indexTable at: (delta bitAnd: deltaValueMask) + 1).
  346.                 index < 0
  347.                     ifTrue: [index _ 0]
  348.                     ifFalse: [index > 88 ifTrue: [index _ 88]].
  349.  
  350.                 samples at: (sampleIndex _ sampleIndex + 1) put: predicted]].
  351. ! !
  352.  
  353. !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'jm 3/29/1999 07:13'!
  354. privateDecodeStereo: count
  355.  
  356.     | predictedLeft predictedRight indexLeft indexRight deltaLeft deltaRight
  357.      stepLeft stepRight predictedDeltaLeft predictedDeltaRight bit |
  358.  
  359.     <primitive: 551>
  360.     self var: #stepSizeTable declareC: 'short int *stepSizeTable'.
  361.     self var: #indexTable declareC: 'short int *indexTable'.
  362.     self var: #samples declareC: 'short int *samples'.
  363.     self var: #encodedBytes declareC: 'unsigned char *encodedBytes'.
  364.     self var: #rightSamples declareC: 'short int *rightSamples'.
  365.     self var: #predicted declareC: 'short int *predicted'.
  366.     self var: #index declareC: 'short int *index'.
  367.  
  368.     "make local copies of decoder state variables"
  369.     predictedLeft _ predicted at: 1.
  370.     predictedRight _ predicted at: 2.
  371.     indexLeft _ index at: 1.
  372.     indexRight _ index at: 2.
  373.  
  374.     1 to: count do: [:i |
  375.         (i bitAnd: frameSizeMask) = 1
  376.             ifTrue: [  "start of frame; read frame header"
  377.                 predictedLeft _ self nextBits: 16.
  378.                 indexLeft _ self nextBits: 6.
  379.                 predictedRight _ self nextBits: 16.
  380.                 indexRight _ self nextBits: 6.
  381.                 predictedLeft > 32767 ifTrue: [predictedLeft _ predictedLeft - 65536].
  382.                 predictedRight > 32767 ifTrue: [predictedRight _ predictedRight - 65536].
  383.                 samples at: (sampleIndex _ sampleIndex + 1) put: predictedLeft.
  384.                 rightSamples at: sampleIndex put: predictedRight]
  385.             ifFalse: [
  386.                 deltaLeft _ self nextBits: bitsPerSample.
  387.                 deltaRight _ self nextBits: bitsPerSample.
  388.                 stepLeft _ stepSizeTable at: indexLeft + 1.
  389.                 stepRight _ stepSizeTable at: indexRight + 1.
  390.                 predictedDeltaLeft _ predictedDeltaRight _ 0.
  391.                 bit _ deltaValueHighBit.
  392.                 [bit > 0] whileTrue: [
  393.                     (deltaLeft bitAnd: bit) > 0 ifTrue: [
  394.                         predictedDeltaLeft _ predictedDeltaLeft + stepLeft].
  395.                     (deltaRight bitAnd: bit) > 0 ifTrue: [
  396.                         predictedDeltaRight _ predictedDeltaRight + stepRight].
  397.                     stepLeft _ stepLeft bitShift: -1.
  398.                     stepRight _ stepRight bitShift: -1.
  399.                     bit _ bit bitShift: -1].
  400.                 predictedDeltaLeft _ predictedDeltaLeft + stepLeft.
  401.                 predictedDeltaRight _ predictedDeltaRight + stepRight.
  402.  
  403.                 (deltaLeft bitAnd: deltaSignMask) > 0
  404.                     ifTrue: [predictedLeft _ predictedLeft - predictedDeltaLeft]
  405.                     ifFalse: [predictedLeft _ predictedLeft + predictedDeltaLeft].
  406.                 (deltaRight bitAnd: deltaSignMask) > 0
  407.                     ifTrue: [predictedRight _ predictedRight - predictedDeltaRight]
  408.                     ifFalse: [predictedRight _ predictedRight + predictedDeltaRight].
  409.                 predictedLeft > 32767
  410.                     ifTrue: [predictedLeft _ 32767]
  411.                     ifFalse: [predictedLeft < -32768 ifTrue: [predictedLeft _ -32768]].
  412.                 predictedRight > 32767
  413.                     ifTrue: [predictedRight _ 32767]
  414.                     ifFalse: [predictedRight < -32768 ifTrue: [predictedRight _ -32768]].
  415.  
  416.                 indexLeft _ indexLeft + (indexTable at: (deltaLeft bitAnd: deltaValueMask) + 1).
  417.                 indexLeft < 0
  418.                     ifTrue: [indexLeft _ 0]
  419.                     ifFalse: [indexLeft > 88 ifTrue: [indexLeft _ 88]].
  420.                 indexRight _ indexRight + (indexTable at: (deltaRight bitAnd: deltaValueMask) + 1).
  421.                 indexRight < 0
  422.                     ifTrue: [indexRight _ 0]
  423.                     ifFalse: [indexRight > 88 ifTrue: [indexRight _ 88]].
  424.  
  425.                 samples at: (sampleIndex _ sampleIndex + 1) put: predictedLeft.
  426.                 rightSamples at: sampleIndex put: predictedRight]].
  427.  
  428.     "save local copies of decoder state variables"
  429.     predicted at: 1 put: predictedLeft.
  430.     predicted at: 2 put: predictedRight.
  431.     index at: 1 put: indexLeft.
  432.     index at: 2 put: indexRight.
  433. ! !
  434.  
  435. !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'jm 3/29/1999 07:13'!
  436. privateEncodeMono: count
  437.  
  438.     | step sign diff delta predictedDelta bit p |
  439.     <primitive: 552>
  440.     self var: #stepSizeTable declareC: 'short int *stepSizeTable'.
  441.     self var: #indexTable declareC: 'short int *indexTable'.
  442.     self var: #samples declareC: 'short int *samples'.
  443.     self var: #encodedBytes declareC: 'unsigned char *encodedBytes'.
  444.  
  445.     step _ stepSizeTable at: 1.
  446.     1 to: count do: [:i |
  447.         (i bitAnd: frameSizeMask) = 1 ifTrue: [
  448.             predicted _ samples at: (sampleIndex _ sampleIndex + 1).
  449.             (p _ predicted) < 0 ifTrue: [p _ p + 65536].
  450.             self nextBits: 16 put: p.
  451.             i < count ifTrue: [
  452.                 index _ self indexForDeltaFrom: predicted to: (samples at: sampleIndex + 1)].
  453.             self nextBits: 6 put: index.
  454.         ] ifFalse: [
  455.             "compute sign and magnitude of difference from the predicted sample"
  456.             sign _ 0.
  457.             diff _ (samples at: (sampleIndex _ sampleIndex + 1)) - predicted.
  458.             diff < 0 ifTrue: [
  459.                 sign _ deltaSignMask.
  460.                 diff _ 0 - diff].
  461.  
  462.             "Compute encoded delta and the difference that this will cause in the predicted sample value during decoding. Note that this code approximates:
  463.                 delta _ (4 * diff) / step.
  464.                 predictedDelta _ ((delta + 0.5) * step) / 4;
  465.             but in the shift step bits are dropped. Thus, even if you have fast mul/div hardware you cannot use it since you would get slightly different bits what than the algorithm defines."
  466.             delta _ 0.
  467.             predictedDelta _ 0.
  468.             bit _ deltaValueHighBit.
  469.             [bit > 0] whileTrue: [
  470.                 diff >= step ifTrue: [
  471.                     delta _ delta + bit.
  472.                     predictedDelta _ predictedDelta + step.
  473.                     diff _ diff - step].
  474.                 step _ step bitShift: -1.
  475.                 bit _ bit bitShift: -1].
  476.             predictedDelta _ predictedDelta + step.
  477.  
  478.             "compute and clamp new prediction"
  479.             sign > 0
  480.                 ifTrue: [predicted _ predicted - predictedDelta]
  481.                 ifFalse: [predicted _ predicted + predictedDelta].
  482.             predicted > 32767
  483.                 ifTrue: [predicted _ 32767]
  484.                 ifFalse: [predicted < -32768 ifTrue: [predicted _ -32768]].
  485.  
  486.             "compute new index and step values"
  487.             index _ index + (indexTable at: delta + 1).
  488.             index < 0
  489.                 ifTrue: [index _ 0]
  490.                 ifFalse: [index > 88 ifTrue: [index _ 88]].
  491.             step _ stepSizeTable at: index + 1.
  492.  
  493.             "output encoded, signed delta"
  494.             self nextBits: bitsPerSample put: (sign bitOr: delta)]].
  495.  
  496.     bitPosition > 0 ifTrue: [  "flush the last output byte, if necessary"
  497.         encodedBytes at: (byteIndex _ byteIndex + 1) put: currentByte].
  498. ! !
  499.  
  500. !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'jm 3/29/1999 07:14'!
  501. privateEncodeStereo: count
  502.  
  503.     <primitive: 553>
  504.     "not yet implemented"
  505.     self inline: false.
  506.     self success: false.! !
  507.  
  508. !ADPCMCodec class methodsFor: 'instance creation' stamp: 'jm 3/27/1999 11:15'!
  509. new
  510.  
  511.     ^ super new
  512.         initializeForBitsPerSample: 4
  513.         samplesPerFrame: 0.
  514. ! !
  515.  
  516. !ADPCMCodec class methodsFor: 'primitive generation' stamp: 'jm 3/28/1999 21:03'!
  517. cCodeForPrimitives
  518.     "Answer a string containing the translated C code for my primitives."
  519.     "Note: This code currently must be hand-edited to remove several methods that are inlined (thus not needed) but not pruned out by the ST-to-C translator."
  520.  
  521.     ^ CCodeGenerator new codeStringForPrimitives: #(
  522.         (ADPCMCodec privateDecodeMono:)
  523.         (ADPCMCodec privateDecodeStereo:)
  524.         (ADPCMCodec privateEncodeMono:)
  525.         (ADPCMCodec privateEncodeStereo:)
  526.         (ADPCMCodec indexForDeltaFrom:to:)
  527.         (ADPCMCodec nextBits:)
  528.         (ADPCMCodec nextBits:put:))
  529. ! !
  530.  
  531. I represent an Apple Event Descriptor.  I am a low-level representation of Apple Event (and hence Applescript) information.  For further Information, see Apple's Inside Macintosh: Interapplication Communications, at
  532.  
  533.     http://developer.apple.com/techpubs/mac/IAC/IAC-2.html.
  534.  
  535. Essentially, I represent a record comprising a one-word "string" (treating the word as fourbyte characters) representing a data type, followed by a pointer to a pointer (a handle) to the data I represent.  Care must be taken to assure that the Handle data is disposed after use, or memory leaks result.  At this time, I make no effort to do this automatically through finalization.!
  536. ]style[(218 54 384)f1,f1Rhttp://developer.apple.com/techpubs/mac/IAC/IAC-2.html;,f1!
  537. !AEDesc methodsFor: 'accessing' stamp: 'acg 9/12/1999 21:33'!
  538. dataSize
  539.  
  540.     ^self handleSizeAt: 2! !
  541.  
  542. !AEDesc methodsFor: 'accessing' stamp: 'acg 9/20/1999 14:22'!
  543. dispose
  544.  
  545.     (0 = (self at: 2)) ifTrue:
  546.         [self error: 'cannot dispose of unallocated space'].
  547.     self primAEDisposeDesc isZero ifFalse: 
  548.         [self error: 'dispose operation failed'].
  549.     self at: 1 put: 0.
  550.     self at: 2 put: 0.
  551.     ^nil! !
  552.  
  553. !AEDesc methodsFor: 'converting' stamp: 'acg 9/24/1999 00:35'!
  554. asCompiledApplescript
  555.  
  556.     | theSize |
  557.     ((self at: 1) ~= 16r73637074) ifTrue:
  558.         [^self error: 'AEDesc is not of type ''scpt'''].
  559.     (theSize _ self dataSize) < 0 ifTrue: [^self error: 'Invalid size for data'].
  560.     ^self primAEDescToString: (CompiledApplescript new: theSize).
  561. ! !
  562.  
  563. !AEDesc methodsFor: 'converting' stamp: 'acg 9/24/1999 00:31'!
  564. asCompiledApplescriptThenDispose
  565.  
  566.     | CAD |
  567.     CAD _ self asCompiledApplescript.
  568.     self dispose.
  569.     ^CAD! !
  570.  
  571. !AEDesc methodsFor: 'converting' stamp: 'acg 9/26/1999 18:39'!
  572. asOSAIDThenDisposeAEDescWith: aComponent
  573.  
  574.     ^aComponent loadAndDisposeAEDesc: self mode: 0! !
  575.  
  576. !AEDesc methodsFor: 'converting' stamp: 'acg 9/23/1999 23:46'!
  577. asShort
  578.  
  579.     ^(self primAEDescToString: (ByteArray new: 2))
  580.         shortAt: 1 bigEndian: true! !
  581.  
  582. !AEDesc methodsFor: 'converting' stamp: 'acg 9/23/1999 23:47'!
  583. asShortThenDispose
  584.  
  585.     | short |
  586.     short _ self asShort.
  587.     self dispose.
  588.     ^short! !
  589.  
  590. !AEDesc methodsFor: 'converting' stamp: 'acg 9/20/1999 14:19'!
  591. asString
  592.  
  593.     | theSize |
  594.     ((self at: 1) ~= 16r54455854) ifTrue:
  595.         [^self error: 'AEDesc is not of type ''TEXT'''].
  596.     (theSize _ self dataSize) < 0 ifTrue: [^self error: 'Invalid size for data'].
  597.     ^self primAEDescToString: (String new: theSize).
  598. ! !
  599.  
  600. !AEDesc methodsFor: 'converting' stamp: 'acg 9/21/1999 00:13'!
  601. asStringThenDispose
  602.  
  603.     | string |
  604.     string _ self asString.
  605.     self dispose.
  606.     ^string! !
  607.  
  608. !AEDesc methodsFor: 'converting' stamp: 'acg 9/26/1999 01:15'!
  609. to: aString
  610.  
  611.     | newAEDesc result |
  612.     newAEDesc _ AEDesc new.
  613.     result _ self primAECoerceDesc: (DescType of: aString) to: newAEDesc.
  614.     result isZero ifFalse: [^result].
  615.     self dispose.
  616.     self at: 1 put: (newAEDesc at: 1).
  617.     self at: 2 put: (newAEDesc at: 2).
  618.     ^0! !
  619.  
  620. !AEDesc methodsFor: 'private' stamp: 'acg 9/24/1999 00:38'!
  621. createFromScpt: aCompiledApplescriptData
  622.  
  623.     (aCompiledApplescriptData class = CompiledApplescript) ifFalse:
  624.         [^self error: 'textType Data Not From CompiledApplescriptData'].
  625.     (self 
  626.         primAECreateDesc: (DescType of: 'scpt')
  627.         from: aCompiledApplescriptData) isZero ifTrue: [^self].
  628.     self error: 'failed to create aeDesc'.
  629.     ^nil! !
  630.  
  631. !AEDesc methodsFor: 'private' stamp: 'acg 9/20/1999 14:39'!
  632. createFromText: aString
  633.  
  634.     (aString class = String) ifFalse:
  635.         [^self error: 'TextType Data Not From String'].
  636.     (self 
  637.         primAECreateDesc: (DescType of: 'TEXT')
  638.         from: aString) isZero ifTrue: [^self].
  639.     self error: 'failed to create aeDesc'.
  640.     ^nil! !
  641.  
  642. !AEDesc methodsFor: 'private' stamp: 'acg 9/25/1999 22:54'!
  643. createNull
  644.  
  645.     (self 
  646.         primAECreateDesc: (DescType of: 'null')
  647.         from: '') isZero ifTrue: [^self].
  648.     self error: 'failed to create aeDesc'.
  649.     ^nil! !
  650.  
  651. !AEDesc methodsFor: 'private' stamp: 'acg 9/23/1999 22:51'!
  652. primAECoerceDesc: typeCode to: result
  653.  
  654.     <primitive: 'primAECoerceDesc' module: 'TestOSAPlugin'>
  655.     ^TestOSAPlugin 
  656.         doPrimitive: 'primAECoerceDesc:to:'
  657.         withArguments: {typeCode. result}! !
  658.  
  659. !AEDesc methodsFor: 'private' stamp: 'acg 9/20/1999 13:25'!
  660. primAECreateDesc: typeCode from: aString
  661.  
  662.     <primitive: 'primAECreateDesc' module: 'TestOSAPlugin'>
  663.     ^TestOSAPlugin 
  664.         doPrimitive: 'primAECreateDesc:from:'    
  665.         withArguments: {typeCode. aString}! !
  666.  
  667. !AEDesc methodsFor: 'private' stamp: 'acg 9/23/1999 21:13'!
  668. primAEDescToString: aString
  669.  
  670.     <primitive: 'primAEDescToString' module: 'TestOSAPlugin'>
  671.     ^TestOSAPlugin 
  672.         doPrimitive: 'primAEDescToString:'
  673.         withArguments: {aString}! !
  674.  
  675. !AEDesc methodsFor: 'private' stamp: 'acg 9/20/1999 13:28'!
  676. primAEDisposeDesc
  677.  
  678.     <primitive: 'primAEDisposeDesc' module: 'TestOSAPlugin'>
  679.     ^TestOSAPlugin 
  680.         doPrimitive: 'primAEDisposeDesc'
  681.         withArguments: {}! !
  682.  
  683. !AEDesc methodsFor: 'private' stamp: 'acg 9/23/1999 22:20'!
  684. primAEGetKeyPtr: keyDesc type: typeDesc actual: ignoreDesc to: aByteArray
  685.  
  686.     <primitive: 'primAEGetKeyPtr' module: 'TestOSAPlugin'>
  687.     ^TestOSAPlugin 
  688.         doPrimitive: 'primAEGetKeyPtr:type:actual:to:'
  689.         withArguments: {keyDesc. typeDesc. ignoreDesc. aByteArray}! !
  690.  
  691. !AEDesc class methodsFor: 'as yet unclassified' stamp: 'acg 9/20/1999 22:17'!
  692. new
  693.  
  694.     ^super new: 2! !
  695.  
  696. !AEDesc class methodsFor: 'as yet unclassified' stamp: 'acg 9/25/1999 22:53'!
  697. nullType
  698.  
  699.     ^self new createNull! !
  700.  
  701. !AEDesc class methodsFor: 'as yet unclassified' stamp: 'acg 9/22/1999 08:05'!
  702. scptTypeOn: aCompiledApplescriptData
  703.  
  704.     ^(self new) createFromScpt: aCompiledApplescriptData
  705.  
  706.         ! !
  707.  
  708. !AEDesc class methodsFor: 'as yet unclassified' stamp: 'acg 9/20/1999 13:30'!
  709. textTypeOn: aString
  710.  
  711.     ^(self new) createFromText: aString
  712.         ! !
  713.  
  714. !AEDesc class methodsFor: 'private' stamp: 'acg 9/12/1999 20:49'!
  715. primSizeAEDesc
  716.  
  717.     <primitive: 'primSizeAEDesc' module: 'OSAPlugin'>
  718.     ^-1! !
  719.  
  720. I am a parser for AIFF (audio interchange file format) files. I can read uncompressed 8-bit and 16-bit mono, stereo, or multichannel AIFF files. I read the marker information used by the TransferStation utility to mark the loop points in sounds extracted from commercial sampled-sound CD-ROMs.
  721. !
  722. !AIFFFileReader methodsFor: 'reading' stamp: 'jm 8/2/1998 16:27'!
  723. readFromFile: fileName
  724.     "Read the AIFF file of the given name."
  725.     "AIFFFileReader new readFromFile: 'test.aiff'"
  726.  
  727.     self readFromFile: fileName
  728.         mergeIfStereo: false
  729.         skipDataChunk: false.
  730. ! !
  731.  
  732. !AIFFFileReader methodsFor: 'reading' stamp: 'jm 3/24/1999 10:39'!
  733. readFromFile: fileName mergeIfStereo: mergeFlag skipDataChunk: skipDataFlag
  734.     "Read the AIFF file of the given name. If mergeFlag is true and the file contains stereo data, then the left and right channels will be mixed together as the samples are read in. If skipDataFlag is true, then the data chunk to be skipped; this allows the other chunks of a file to be processed in order to extract format information quickly without reading the data."
  735.     "AIFFFileReader new readFromFile: 'test.aiff' mergeIfStereo: false skipDataChunk: true"
  736.  
  737.     | f |
  738.     mergeIfStereo _ mergeFlag.
  739.     skipDataChunk _ skipDataFlag.
  740.     f _ (FileStream readOnlyFileNamed: fileName) binary.
  741.     isLooped _ false.
  742.     gain _ 1.0.
  743.     self readFrom: f.
  744.     f close.
  745. ! !
  746.  
  747. !AIFFFileReader methodsFor: 'accessing' stamp: 'jm 8/2/1998 21:25'!
  748. bitsPerSample
  749.  
  750.     ^ bitsPerSample
  751. ! !
  752.  
  753. !AIFFFileReader methodsFor: 'accessing' stamp: 'jm 8/2/1998 21:24'!
  754. channelCount
  755.  
  756.     ^ channelCount
  757. ! !
  758.  
  759. !AIFFFileReader methodsFor: 'accessing' stamp: 'jm 8/2/1998 21:25'!
  760. channelData
  761.  
  762.     ^ channelData
  763. ! !
  764.  
  765. !AIFFFileReader methodsFor: 'accessing' stamp: 'jm 8/2/1998 21:24'!
  766. frameCount
  767.  
  768.     ^ frameCount
  769. ! !
  770.  
  771. !AIFFFileReader methodsFor: 'accessing' stamp: 'jm 8/2/1998 21:25'!
  772. gain
  773.  
  774.     ^ gain
  775. ! !
  776.  
  777. !AIFFFileReader methodsFor: 'accessing' stamp: 'jm 7/12/1998 01:40'!
  778. isLooped
  779.  
  780.     ^ isLooped
  781. ! !
  782.  
  783. !AIFFFileReader methodsFor: 'accessing' stamp: 'jm 8/2/1998 20:02'!
  784. isStereo
  785.  
  786.     ^ channelData size = 2
  787. ! !
  788.  
  789. !AIFFFileReader methodsFor: 'accessing' stamp: 'jm 7/12/1998 18:26'!
  790. leftSamples
  791.  
  792.     ^ channelData at: 1
  793. ! !
  794.  
  795. !AIFFFileReader methodsFor: 'accessing' stamp: 'jm 7/12/1998 18:30'!
  796. loopEnd
  797.  
  798.     ^ markers last last
  799. ! !
  800.  
  801. !AIFFFileReader methodsFor: 'accessing' stamp: 'jm 7/12/1998 18:30'!
  802. loopLength
  803.  
  804.     ^ markers last last - markers first last
  805. ! !
  806.  
  807. !AIFFFileReader methodsFor: 'accessing' stamp: 'jm 8/2/1998 21:25'!
  808. markers
  809.  
  810.     ^ markers
  811. ! !
  812.  
  813. !AIFFFileReader methodsFor: 'accessing' stamp: 'jm 7/12/1998 01:48'!
  814. pitch
  815.  
  816.     ^ pitch
  817. ! !
  818.  
  819. !AIFFFileReader methodsFor: 'accessing' stamp: 'jm 8/2/1998 19:34'!
  820. rightSamples
  821.  
  822.     ^ channelData at: 2
  823. ! !
  824.  
  825. !AIFFFileReader methodsFor: 'accessing' stamp: 'jm 7/12/1998 18:25'!
  826. samplingRate
  827.  
  828.     ^ samplingRate
  829. ! !
  830.  
  831. !AIFFFileReader methodsFor: 'other' stamp: 'jm 8/17/1998 20:36'!
  832. edit
  833.  
  834.     | ed |
  835.     ed _ WaveEditor new.
  836.     ed data: channelData first.
  837.     ed loopEnd: markers last last.
  838.     ed loopLength: (markers last last - markers first last) + 1.
  839.     ed openInWorld.
  840. ! !
  841.  
  842. !AIFFFileReader methodsFor: 'other' stamp: 'jm 7/12/1998 01:44'!
  843. pitchForKey: midiKey
  844.     "Convert my MIDI key number to a pitch and return it."
  845.  
  846.     | indexInOctave octave p |
  847.     indexInOctave _ (midiKey \\ 12) + 1.
  848.     octave _ (midiKey // 12) + 1.
  849.     "Table generator: (0 to: 11) collect: [:i | 16.3516 * (2.0 raisedTo: i asFloat / 12.0)]"
  850.     p _ #(16.3516 17.32391 18.35405 19.44544 20.60173 21.82677
  851.           23.12466 24.49972 25.95655 27.50000 29.13524 30.86771) at: indexInOctave.
  852.     ^ p * (#(0.5 1.0 2.0 4.0 8.0 16.0 32.0 64.0 128.0 256.0 512.0) at: octave)
  853. ! !
  854.  
  855. !AIFFFileReader methodsFor: 'other' stamp: 'jm 1/14/1999 10:11'!
  856. sound
  857.     "Answer the sound represented by this AIFFFileReader. This method should be called only after readFrom: has been done."
  858.  
  859.     | snd rightSnd |
  860.     snd _ SampledSound
  861.         samples: (channelData at: 1)
  862.         samplingRate: samplingRate.
  863.     self isStereo ifTrue: [
  864.         rightSnd _ SampledSound
  865.             samples: (channelData at: 2)
  866.             samplingRate: samplingRate.
  867.         snd _ MixedSound new
  868.             add: snd pan: 0;
  869.             add: rightSnd pan: 1.0].
  870.     ^ snd
  871. ! !
  872.  
  873. !AIFFFileReader methodsFor: 'private' stamp: 'jm 6/29/1998 07:33'!
  874. readChunk: chunkType size: chunkSize
  875.     "Read a AIFF chunk of the given type. Skip unrecognized chunks. Leave the input stream positioned chunkSize bytes past its position when this method is called."
  876.  
  877.     chunkType = 'COMM' ifTrue: [^ self readCommonChunk: chunkSize].
  878.     chunkType = 'SSND' ifTrue: [^ self readSamplesChunk: chunkSize].
  879.     chunkType = 'INST' ifTrue: [^ self readInstrumentChunk: chunkSize].
  880.     chunkType = 'MARK' ifTrue: [^ self readMarkerChunk: chunkSize].
  881.     in skip: chunkSize.  "skip unknown chunks"
  882. ! !
  883.  
  884. !AIFFFileReader methodsFor: 'private' stamp: 'jm 7/12/1998 18:24'!
  885. readCommonChunk: chunkSize
  886.     "Read a COMM chunk. All AIFF files have exactly one chunk of this type."
  887.  
  888.     | compressionType |
  889.     channelCount _ in nextNumber: 2.
  890.     frameCount _ in nextNumber: 4.
  891.     bitsPerSample _ in nextNumber: 2.
  892.     samplingRate _ self readExtendedFloat.
  893.     chunkSize > 18 ifTrue: [
  894.         fileType = 'AIFF'
  895.             ifTrue: [self error: 'unexpectedly long COMM chunk size for AIFF file'].
  896.         compressionType _ (in next: 4) asString.
  897.         compressionType = 'NONE' ifFalse: [self error: 'cannot read compressed AIFF files'].
  898.         in skip: (chunkSize - 22)].  "skip the reminder of AIFF-C style chunk"
  899. ! !
  900.  
  901. !AIFFFileReader methodsFor: 'private' stamp: 'jm 6/29/1998 11:43'!
  902. readExtendedFloat
  903.     "Read and answer an Apple extended-precision 80-bit floating point number from the input stream."
  904.     "Details: I could not find the specification for this format, so constants were determined empirically based on assumption of 1-bit sign, 15-bit exponent, 64-bit mantissa. This format does not seem to have an implicit one before the mantissa as some float formats do."
  905.  
  906.     | signAndExp mantissa sign exp |
  907.     signAndExp _ in nextNumber: 2.
  908.     mantissa _ in nextNumber: 8.  "scaled by (2 raisedTo: -64) below"
  909.     (signAndExp bitAnd: 16r8000) = 0
  910.         ifTrue: [sign _ 1.0]
  911.         ifFalse: [sign _ -1.0].
  912.     exp _ (signAndExp bitAnd: 16r7FFF) - 16r4000 + 2.  "not sure why +2 is needed..."
  913.     ^ (sign * mantissa asFloat * (2.0 raisedTo: exp - 64)) roundTo: 0.00000001
  914. ! !
  915.  
  916. !AIFFFileReader methodsFor: 'private' stamp: 'jm 8/2/1998 19:58'!
  917. readFrom: aBinaryStream
  918.     "Read AIFF data from the given binary stream."
  919.     "Details: An AIFF file consists of a header (FORM chunk) followed by a sequence of tagged data chunks. Each chunk starts with a header consisting of a four-byte tag (a string) and a four byte size. These eight bytes of chunk header are not included in the chunk size. For each chunk, the readChunk:size: method consumes chunkSize bytes of the input stream, parsing recognized chunks or skipping unrecognized ones. If chunkSize is odd, it will be followed by a padding byte. Chunks may occur in any order."
  920.  
  921.     | sz end chunkType chunkSize p |
  922.     in _ aBinaryStream.
  923.  
  924.     "read FORM chunk"
  925.     (in next: 4) asString = 'FORM' ifFalse: [^ self error: 'not an AIFF file'].
  926.     sz _ in nextNumber: 4.
  927.     end _ in position + sz.
  928.     fileType _ (in next: 4) asString.
  929.  
  930.     [in atEnd not and: [in position < end]] whileTrue: [
  931.         chunkType _ (in next: 4) asString.
  932.         chunkSize _ in nextNumber: 4.
  933.         p _ in position.
  934.         self readChunk: chunkType size: chunkSize.
  935.         (in position = (p + chunkSize))
  936.             ifFalse: [self error: 'chunk size mismatch; bad AIFF file?'].
  937.         chunkSize odd ifTrue: [in skip: 1]].  "skip padding byte"
  938. ! !
  939.  
  940. !AIFFFileReader methodsFor: 'private' stamp: 'jm 8/5/1998 17:31'!
  941. readInstrumentChunk: chunkSize
  942.  
  943.     | midiKey detune lowNote highNote lowVelocity highVelocity
  944.       sustainMode sustainStartID sustainEndID
  945.       releaseMode releaseStartID releaseEndID |
  946.  
  947.     midiKey _ in next.
  948.     detune _ in next.
  949.     lowNote _ in next.
  950.     highNote _ in next.
  951.     lowVelocity _ in next.
  952.     highVelocity _ in next.
  953.     gain _ in nextNumber: 2.
  954.     sustainMode _ in nextNumber: 2.
  955.     sustainStartID _ in nextNumber: 2.
  956.     sustainEndID _ in nextNumber: 2.
  957.     releaseMode _ in nextNumber: 2.
  958.     releaseStartID _ in nextNumber: 2.
  959.     releaseEndID _ in nextNumber: 2.
  960.     isLooped _ sustainMode = 1.
  961.     (isLooped and: [markers notNil]) ifTrue: [
  962.         ((markers first last > frameCount) or:
  963.          [markers last last > frameCount]) ifTrue: [
  964.             "bad loop data; some sample CD files claim to be looped but aren't"
  965.             isLooped _ false]].
  966.     pitch _ self pitchForKey: midiKey.
  967. ! !
  968.  
  969. !AIFFFileReader methodsFor: 'private' stamp: 'jm 8/2/1998 21:22'!
  970. readMarkerChunk: chunkSize
  971.  
  972.     | markerCount id position labelBytes label |
  973.     markerCount _ in nextNumber: 2.
  974.     markers _ Array new: markerCount.
  975.     1 to: markerCount do: [:i |
  976.         id _ in nextNumber: 2.
  977.         position _ in nextNumber: 4.
  978.         labelBytes _ in next.
  979.         label _ (in next: labelBytes) asString.
  980.         labelBytes even ifTrue: [in skip: 1].
  981.         markers at: i put: (Array with: id with: label with: position)].
  982.  
  983. ! !
  984.  
  985. !AIFFFileReader methodsFor: 'private' stamp: 'jm 8/2/1998 18:58'!
  986. readMergedStereoChannelDataFrom: s
  987.     "Read stereophonic channel data from the given stream, mixing the two channels to create a single monophonic channel. Each frame contains two samples."
  988.  
  989.     | buf w1 w2 |
  990.     buf _ channelData at: 1.
  991.     bitsPerSample = 8
  992.         ifTrue: [
  993.             1 to: frameCount do: [:i |
  994.                 w1 _ s next.
  995.                 w1 > 127 ifTrue: [w1 _ w1 - 256].
  996.                 w2 _ s next.
  997.                 w2 > 127 ifTrue: [w2 _ w2 - 256].
  998.                 buf at: i put: ((w1 + w2) bitShift: 7)]]
  999.         ifFalse: [
  1000.             1 to: frameCount do: [:i |
  1001.                 w1 _ (s next bitShift: 8) + s next.
  1002.                 w1 > 32767 ifTrue: [w1 _ w1 - 65536].
  1003.                 w2 _ (s next bitShift: 8) + s next.
  1004.                 w2 > 32767 ifTrue: [w2 _ w2 - 65536].
  1005.                 buf at: i put: ((w1 + w2) bitShift: -1)]].
  1006. ! !
  1007.  
  1008. !AIFFFileReader methodsFor: 'private' stamp: 'jm 8/2/1998 18:53'!
  1009. readMonoChannelDataFrom: s
  1010.     "Read monophonic channel data from the given stream. Each frame contains a single sample."
  1011.  
  1012.     | buf w |
  1013.     buf _ channelData at: 1.  "the only buffer"
  1014.     bitsPerSample = 8
  1015.         ifTrue: [
  1016.             1 to: frameCount do: [:i |
  1017.                 w _ s next.
  1018.                 w > 127 ifTrue: [w _ w - 256].
  1019.                 buf at: i put: (w bitShift: 8)]]
  1020.         ifFalse: [
  1021.             1 to: frameCount do: [:i |
  1022.                 w _ (s next bitShift: 8) + s next.
  1023.                 w > 32767 ifTrue: [w _ w - 65536].
  1024.                 buf at: i put: w]].
  1025. ! !
  1026.  
  1027. !AIFFFileReader methodsFor: 'private' stamp: 'jm 8/2/1998 18:55'!
  1028. readMultiChannelDataFrom: s
  1029.     "Read multi-channel data from the given stream. Each frame contains channelCount samples."
  1030.  
  1031.     | w |
  1032.     bitsPerSample = 8
  1033.         ifTrue: [
  1034.             1 to: frameCount do: [:i |
  1035.                 1 to: channelCount do: [:ch |
  1036.                     w _ s next.
  1037.                     w > 127 ifTrue: [w _ w - 256].
  1038.                     (channelData at: ch) at: i put: (w bitShift: 8)]]]
  1039.         ifFalse: [
  1040.             1 to: frameCount do: [:i |
  1041.                 1 to: channelCount do: [:ch |
  1042.                     w _ (s next bitShift: 8) + s next.
  1043.                     w > 32767 ifTrue: [w _ w - 65536].
  1044.                     (channelData at: ch) at: i put: w]]].
  1045. ! !
  1046.  
  1047. !AIFFFileReader methodsFor: 'private' stamp: 'jm 8/3/1998 14:55'!
  1048. readSamplesChunk: chunkSize
  1049.     "Read a SSND chunk. All AIFF files with a non-zero frameCount contain exactly one chunk of this type."
  1050.  
  1051.     | offset blockSize bytesOfSamples s |
  1052.     skipDataChunk ifTrue: [in skip: chunkSize. ^ self].
  1053.  
  1054.     offset _ in nextNumber: 4.
  1055.     blockSize _ in nextNumber: 4.
  1056.     ((offset ~= 0) or: [blockSize ~= 0])
  1057.         ifTrue: [^ self error: 'this AIFF reader cannot handle blocked sample chunks'].
  1058.     bytesOfSamples _ chunkSize - 8.
  1059.     bytesOfSamples = (channelCount * frameCount * (bitsPerSample // 8))
  1060.         ifFalse: [self error: 'actual sample count does not match COMM chunk'].
  1061.     (mergeIfStereo and: [channelCount = 2])
  1062.         ifTrue: [
  1063.             channelData _ Array with: (SoundBuffer newMonoSampleCount: frameCount)]
  1064.         ifFalse: [
  1065.             channelData _
  1066.                 (1 to: channelCount) collect: [:i | SoundBuffer newMonoSampleCount: frameCount]].
  1067.  
  1068.     (bytesOfSamples < (Smalltalk garbageCollectMost - 300000))
  1069.         ifTrue: [s _ ReadStream on: (in next: bytesOfSamples)]  "bulk-read, then process"
  1070.         ifFalse: [s _ in].  "not enough space to buffer; read directly from file"
  1071.  
  1072.     "mono and stereo are special-cased for better performance"
  1073.     channelCount = 1 ifTrue: [^ self readMonoChannelDataFrom: s].
  1074.     channelCount = 2 ifTrue: [
  1075.         mergeIfStereo
  1076.             ifTrue: [channelCount _ 1. ^ self readMergedStereoChannelDataFrom: s]
  1077.             ifFalse: [^ self readStereoChannelDataFrom: s]].
  1078.     self readMultiChannelDataFrom: s.
  1079. ! !
  1080.  
  1081. !AIFFFileReader methodsFor: 'private' stamp: 'jm 8/2/1998 18:56'!
  1082. readStereoChannelDataFrom: s
  1083.     "Read stereophonic channel data from the given stream. Each frame contains two samples."
  1084.  
  1085.     | left right w |
  1086.     left _ channelData at: 1.
  1087.     right _ channelData at: 2.
  1088.     bitsPerSample = 8
  1089.         ifTrue: [
  1090.             1 to: frameCount do: [:i |
  1091.                 w _ s next.
  1092.                 w > 127 ifTrue: [w _ w - 256].
  1093.                 left at: i put: (w bitShift: 8).
  1094.                 w _ s next.
  1095.                 w > 127 ifTrue: [w _ w - 256].
  1096.                 right at: i put: (w bitShift: 8)]]
  1097.         ifFalse: [
  1098.             1 to: frameCount do: [:i |
  1099.                 w _ (s next bitShift: 8) + s next.
  1100.                 w > 32767 ifTrue: [w _ w - 65536].
  1101.                 left at: i put: w.
  1102.                 w _ (s next bitShift: 8) + s next.
  1103.                 w > 32767 ifTrue: [w _ w - 65536].
  1104.                 right at: i put: w]].
  1105. ! !
  1106.  
  1107. An AbsoluteAnimation is any animation where the final state of the animation is always the same. Every time this animation runs we store the initial state, so that when the animation is reversed and run we can determine what that end point should be.
  1108. !
  1109. !AbsoluteAnimation methodsFor: 'management' stamp: 'jsp 2/16/1999 16:36'!
  1110. prologue: currentTime
  1111.     "Extends the AbstractAnimation prologue by saving the start state of the animation."
  1112.  
  1113.     undoable ifTrue: [
  1114.                         (myWonderland getUndoStack)
  1115.                                 push: (UndoAnimation new: (self makeUndoVersion)).
  1116.                     ].
  1117.  
  1118.     (direction = Forward) ifTrue: [
  1119.                                     startState _ getStartStateFunction value.
  1120.                                     lastStartState _ startState.
  1121.                                     endState _ getEndStateFunction value.
  1122.                                 ]
  1123.                         ifFalse: [
  1124.                                     startState _ getStartStateFunction value.
  1125.                                     endState _ lastStartState.
  1126.                                 ].
  1127.  
  1128.  
  1129.     super prologue: currentTime.
  1130. ! !
  1131.  
  1132. !AbsoluteAnimation methodsFor: 'initialization' stamp: 'jsp 3/9/1999 15:49'!
  1133. object: anObject update: func getStartState: startFunc getEndState: endFunc style: styleFunc duration: time undoable: canUndo inWonderland: aWonderland
  1134.     "This method initializes the Animation with all the information that it needs to run."
  1135.  
  1136.     lastStartState _ startFunc value.
  1137.  
  1138.     super object: anObject update: func getStartState: startFunc getEndState: endFunc style: styleFunc duration: time undoable: canUndo inWonderland: aWonderland.
  1139. ! !
  1140.  
  1141. !AbsoluteAnimation methodsFor: 'copying' stamp: 'jsp 3/9/1999 15:49'!
  1142. copy
  1143.     "Creates a copy of the animation"
  1144.  
  1145.     | anim |
  1146.  
  1147.     anim _ AbsoluteAnimation new.
  1148.  
  1149.     anim object: animatedObject
  1150.         update: updateFunction
  1151.         getStartState: getStartStateFunction
  1152.         getEndState: getEndStateFunction
  1153.         style: styleFunction
  1154.         duration: duration
  1155.         undoable: undoable
  1156.         inWonderland: myWonderland.
  1157.  
  1158.     (direction = Forward) ifFalse: [ anim reverseDirection ].
  1159.  
  1160.     ^ anim.
  1161. ! !
  1162.  
  1163. !AbsoluteAnimation methodsFor: 'copying' stamp: 'jsp 3/9/1999 15:49'!
  1164. makeUndoVersion
  1165.     "Creates the undo version of an animation"
  1166.  
  1167.     | anim |
  1168.  
  1169.     anim _ AbsoluteAnimation new.
  1170.  
  1171.     anim object: animatedObject
  1172.         update: updateFunction
  1173.         getStartState: getStartStateFunction
  1174.         getEndState: getEndStateFunction
  1175.         style: styleFunction
  1176.         duration: 0.5
  1177.         undoable: false
  1178.         inWonderland: myWonderland.
  1179.  
  1180.     anim stop.
  1181.     (direction = Forward) ifTrue: [ anim reverseDirection ].
  1182.  
  1183.     ^ anim.
  1184. ! !
  1185.  
  1186. !AbsoluteAnimation methodsFor: 'copying' stamp: 'jsp 4/9/1999 14:22'!
  1187. reversed
  1188.     "Creates a reversed version of an animation"
  1189.  
  1190.     | anim |
  1191.  
  1192.     anim _ AbsoluteAnimation new.
  1193.  
  1194.     anim object: animatedObject
  1195.         update: updateFunction
  1196.         getStartState: getStartStateFunction
  1197.         getEndState: getEndStateFunction
  1198.         style: styleFunction
  1199.         duration: duration
  1200.         undoable: true
  1201.         inWonderland: myWonderland.
  1202.  
  1203.     anim stop.
  1204.     (direction = Forward) ifTrue: [ anim reverseDirection ].
  1205.  
  1206.     ^ anim.
  1207. ! !
  1208.  
  1209. This class implements the basic functionality of Animations for Wonderlands. All animations pass through 4 specific stages:
  1210.  
  1211. Waiting - this is the state animations are in when they are just started, before they run their prologue (perform any tasks they need to do before the animation actually starts)
  1212.  
  1213. Running - this is the state animations are in when they are actually running
  1214.  
  1215. Stopped - this is the state animations are in after they stop running but before they execute their prologue
  1216.  
  1217. Finished - this is the state animations are in after they finish their epilogue (perform any tasks they need to do after the animation completes).
  1218. !
  1219. !AbstractAnimation methodsFor: 'accessing' stamp: 'jsp 3/9/1999 15:45'!
  1220. getAnimatedObject
  1221.     "Return the object that this animation affects"
  1222.  
  1223.     ^ animatedObject.
  1224. ! !
  1225.  
  1226. !AbstractAnimation methodsFor: 'accessing' stamp: 'jsp 2/26/1999 12:41'!
  1227. getLoopCount
  1228.     "Returns the animation's current loop count"
  1229.  
  1230.     ^ loopCount.
  1231. ! !
  1232.  
  1233. !AbstractAnimation methodsFor: 'accessing' stamp: 'jsp 2/4/1999 10:22'!
  1234. getState
  1235.     "Returns the current state of the animation."
  1236.  
  1237.     ^ state.
  1238. ! !
  1239.  
  1240. !AbstractAnimation methodsFor: 'accessing' stamp: 'jsp 2/3/1999 14:23'!
  1241. isDone
  1242.     "Returns true if the animation is running"
  1243.  
  1244.     ^ (state = Stopped).
  1245. ! !
  1246.  
  1247. !AbstractAnimation methodsFor: 'accessing' stamp: 'jsp 2/26/1999 12:01'!
  1248. isLooping
  1249.     "Returns true if the animation is looping"
  1250.  
  1251.     ^ ( loopCount > 1) or: [ loopCount = Infinity ].
  1252. ! !
  1253.  
  1254. !AbstractAnimation methodsFor: 'accessing' stamp: 'jsp 2/26/1999 12:42'!
  1255. setLoopCount: count
  1256.     "Sets the animation's current loop count"
  1257.  
  1258.     loopCount _ count.
  1259.  
  1260. ! !
  1261.  
  1262. !AbstractAnimation methodsFor: 'accessing' stamp: 'jsp 2/26/1999 12:23'!
  1263. setUndoable: aBoolean
  1264.     "Sets the animation's undoable property"
  1265.  
  1266.     undoable _ aBoolean.
  1267. ! !
  1268.  
  1269. !AbstractAnimation methodsFor: 'management' stamp: 'jsp 3/3/1999 12:38'!
  1270. copy
  1271.  
  1272.     self subclassResponsibility.
  1273. ! !
  1274.  
  1275. !AbstractAnimation methodsFor: 'management' stamp: 'jsp 3/3/1999 12:06'!
  1276. epilogue: currentTime
  1277.     "This method does any work that needs to be done after an interation of the animation finishes."
  1278.  
  1279.     (loopCount = Infinity) ifTrue:
  1280.                 [state _ Waiting]
  1281.     ifFalse:
  1282.                 [
  1283.                     loopCount _ loopCount - 1.
  1284.  
  1285.                     (loopCount > 0) ifTrue: [ state _ Waiting ]
  1286.                                     ifFalse: [state _ Stopped.
  1287.                                              loopCount _ 1 ].
  1288.                 ].
  1289.  
  1290. ! !
  1291.  
  1292. !AbstractAnimation methodsFor: 'management' stamp: 'jsp 2/3/1999 14:47'!
  1293. getDuration
  1294.     "This method returns the duration of the animation."
  1295.  
  1296.     ^ duration.
  1297. ! !
  1298.  
  1299. !AbstractAnimation methodsFor: 'management' stamp: 'jsp 3/24/1999 15:48'!
  1300. loop
  1301.     "This method causes an animation to loop forever."
  1302.  
  1303.     loopCount _ Infinity.
  1304.  
  1305.     (state = Stopped) ifTrue: [ state _ Waiting.
  1306.                               myScheduler addAnimation: self. ].
  1307. ! !
  1308.  
  1309. !AbstractAnimation methodsFor: 'management' stamp: 'jsp 2/3/1999 15:10'!
  1310. loop: numberOfTimes
  1311.     "This method causes an animation to loop for the specified number of times."
  1312.  
  1313.     loopCount _ numberOfTimes.
  1314.  
  1315.     (state = Stopped) ifTrue: [ state _ Waiting.
  1316.                               myScheduler addAnimation: self. ].
  1317. ! !
  1318.  
  1319. !AbstractAnimation methodsFor: 'management' stamp: 'jsp 3/3/1999 12:37'!
  1320. looped
  1321.     "This method creates a copy of an animation and loops it forever."
  1322.  
  1323.     | anim |
  1324.  
  1325.     anim _ self copy.
  1326.     anim setLoopCount: Infinity.
  1327.  
  1328.     ^ anim.
  1329. ! !
  1330.  
  1331. !AbstractAnimation methodsFor: 'management' stamp: 'jsp 3/3/1999 12:36'!
  1332. looped: numberOfTimes
  1333.     "This method creates a copy of an animation and loops it for the specified number of times."
  1334.  
  1335.     | anim |
  1336.  
  1337.     anim _ self copy.
  1338.     anim setLoopCount: numberOfTimes.
  1339.  
  1340.     ^ anim.
  1341. ! !
  1342.  
  1343. !AbstractAnimation methodsFor: 'management' stamp: 'jsp 2/3/1999 14:43'!
  1344. pause
  1345.     "This method pauses an active Animation."
  1346.  
  1347.     (state = Running) ifTrue: [ state _ Paused. 
  1348.                                 pausedInterval _ (myScheduler getTime) - startTime.].
  1349. ! !
  1350.  
  1351. !AbstractAnimation methodsFor: 'management' stamp: 'jsp 2/3/1999 14:56'!
  1352. prologue: currentTime
  1353.     "This method does any work that needs to be done before the animation starts, including possibly adding the current state to the undo stack."
  1354.  
  1355.     "Undo stack stuff here"
  1356.     undoable ifTrue: [].
  1357.  
  1358.     startTime _ currentTime.
  1359.     endTime _ startTime + duration.
  1360.     state _ Running.
  1361. ! !
  1362.  
  1363. !AbstractAnimation methodsFor: 'management' stamp: 'jsp 2/26/1999 15:21'!
  1364. resume
  1365.     "This method resumes a paused animation"
  1366.  
  1367.     (state = Paused) ifTrue:
  1368.         [
  1369.             state _ Running.
  1370.             startTime _ (myScheduler getTime) - pausedInterval.
  1371.             endTime _ startTime + duration.
  1372.         ]
  1373.     ifFalse: [(state = Stopped) ifTrue:
  1374.                 [
  1375.                     state _ Waiting.
  1376.                     myScheduler addAnimation: self.
  1377.                 ].
  1378.             ]
  1379.  
  1380.  
  1381. ! !
  1382.  
  1383. !AbstractAnimation methodsFor: 'management' stamp: 'jsp 2/3/1999 15:00'!
  1384. start
  1385.     "This method starts an existing animation"
  1386.  
  1387.     state _ Waiting.
  1388.     loopCount _ 1.
  1389.     myScheduler addAnimation: self.
  1390. ! !
  1391.  
  1392. !AbstractAnimation methodsFor: 'management' stamp: 'jsp 2/3/1999 14:25'!
  1393. stop
  1394.     "This method changes the state of an animation to stopped.  If it is currently active, the Scheduler will remove it from the list of active animations."
  1395.  
  1396.     state _ Stopped.
  1397. ! !
  1398.  
  1399. !AbstractAnimation methodsFor: 'management' stamp: 'jsp 2/3/1999 14:50'!
  1400. stopLooping
  1401.     "This method causes the animation to stop looping; the current interation of the animation completes before the animation stops."
  1402.  
  1403.     loopCount _ 1.
  1404. ! !
  1405.  
  1406. !AbstractAnimation methodsFor: 'management' stamp: 'jsp 2/3/1999 14:53'!
  1407. update: currentTime
  1408.     "Updates the animation using the current Wonderland time"
  1409.  
  1410.     (state = Waiting) ifTrue: [self prologue: currentTime].
  1411.  
  1412.     (state = Running) ifTrue: [].
  1413.  
  1414.     (state = Finished) ifTrue: [self epilogue: currentTime].
  1415. ! !
  1416.  
  1417. !AbstractAnimation methodsFor: 'reversing' stamp: 'jsp 2/15/1999 10:28'!
  1418. reverseDirection
  1419.     "Changes the direction an animation runs in (forward or in reverse)"
  1420.  
  1421.     (direction = Forward) ifTrue: [ direction _ Reverse ]
  1422.                          ifFalse: [ direction _ Forward ].
  1423. ! !
  1424.  
  1425. !AbstractAnimation methodsFor: 'private' stamp: 'jsp 2/26/1999 14:21'!
  1426. scaleDuration: scaleAmount
  1427.     "Scales the animation's duration by the specified amount"
  1428.  
  1429.     duration _ duration * scaleAmount.
  1430. ! !
  1431.  
  1432. !AbstractAnimation methodsFor: 'private' stamp: 'jsp 2/26/1999 14:17'!
  1433. setDirection: aDirection
  1434.     "Sets the animation's direction variable"
  1435.  
  1436.     direction _ aDirection.
  1437. ! !
  1438.  
  1439. !AbstractAnimation class methodsFor: 'class initialization' stamp: 'jsp 3/24/1999 11:01'!
  1440. initialize
  1441.     "Initialize the class variables"
  1442.  
  1443.     Waiting _ 1.
  1444.     Running _ 2.
  1445.     Paused _ 3.
  1446.     Finished _ 4.
  1447.     Stopped _ 5.
  1448.  
  1449.     Forward _ 0.
  1450.     Reverse _ 1.
  1451.  
  1452.     Infinity _ -1.
  1453. ! !
  1454.  
  1455. AbstractFont defines the generic interface that all fonts need to implement.!
  1456. !AbstractFont methodsFor: 'accessing' stamp: 'ar 5/19/2000 14:56'!
  1457. characterToGlyphMap
  1458.     "Return the character to glyph mapping table. If the table is not provided the character scanner will query the font directly for the width of each individual character."
  1459.     ^nil! !
  1460.  
  1461. !AbstractFont methodsFor: 'accessing' stamp: 'ar 5/19/2000 14:57'!
  1462. xTable
  1463.     "Return the xTable for the font. The xTable defines the left x-value for each individual glyph in the receiver. If such a table is not provided, the character scanner will ask the font directly for the appropriate width of each individual character."
  1464.     ^nil! !
  1465.  
  1466. !AbstractFont methodsFor: 'measuring' stamp: 'ar 5/19/2000 15:00'!
  1467. composeWord: aTextLineInterval in: sourceString beginningAt: xInteger 
  1468.     "Non-primitive composition of a word--add up widths of characters, add 
  1469.     sum to beginning x and answer the resulting x. Similar to performance 
  1470.     of scanning primitive, but without stop conditions."
  1471.  
  1472.     | character resultX |
  1473.     resultX _ xInteger.
  1474.     aTextLineInterval do: 
  1475.         [:i | 
  1476.         character _ sourceString at: i.
  1477.         resultX _ resultX + (self widthOf: character)].
  1478.     ^resultX! !
  1479.  
  1480. !AbstractFont methodsFor: 'measuring' stamp: 'ar 5/19/2000 14:58'!
  1481. widthOf: aCharacter
  1482.     "Return the width of the given character"
  1483.     ^self subclassResponsibility! !
  1484.  
  1485. !AbstractFont methodsFor: 'measuring' stamp: 'ar 5/19/2000 15:00'!
  1486. widthOfString: aString
  1487.  
  1488.     ^ self composeWord: (1 to: aString size) in: aString beginningAt: 0
  1489. "
  1490.     TextStyle default defaultFont widthOfString: 'zort' 21
  1491. "! !
  1492.  
  1493. !AbstractFont methodsFor: 'displaying' stamp: 'ar 5/19/2000 14:59'!
  1494. displayString: aString on: aDisplayContext from: startIndex to: stopIndex at: aPoint kern: kernDelta
  1495.     "Draw the given string from startIndex to stopIndex 
  1496.     at aPoint on the (already prepared) display context."
  1497.     ^self subclassResponsibility! !
  1498.  
  1499. !AbstractFont methodsFor: 'displaying' stamp: 'ar 5/19/2000 14:59'!
  1500. installOn: aDisplayContext foregroundColor: foregroundColor backgroundColor: backgroundColor
  1501.     "Install the receiver on the given DisplayContext (either BitBlt or Canvas) for further drawing operations."
  1502.     ^self subclassResponsibility! !
  1503.  
  1504. Contributed by Bob Arning as part of the ObjectExplorer package.
  1505. !
  1506. !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 15:22'!
  1507. genericMenu: aMenu
  1508.  
  1509.     aMenu add: 'no menu yet' target: self selector: #yourself.
  1510.     ^aMenu! !
  1511.  
  1512. !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:44'!
  1513. getCurrentSelection
  1514.  
  1515.     ^currentSelection! !
  1516.  
  1517. !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:46'!
  1518. noteNewSelection: x
  1519.  
  1520.     currentSelection _ x.
  1521.     self changed: #getCurrentSelection.
  1522.     currentSelection ifNil: [^self].
  1523.     currentSelection sendSettingMessageTo: self.
  1524. ! !
  1525.  
  1526. !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:53'!
  1527. perform: selector orSendTo: otherTarget
  1528.     "Selector was just chosen from a menu by a user.  If can respond, then
  1529. perform it on myself. If not, send it to otherTarget, presumably the
  1530. editPane from which the menu was invoked."
  1531.  
  1532.     (self respondsTo: selector)
  1533.         ifTrue: [^ self perform: selector]
  1534.         ifFalse: [^ otherTarget perform: selector]! !
  1535.  
  1536. !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:47'!
  1537. update: aSymbol
  1538.  
  1539.     aSymbol == #hierarchicalList ifTrue: [
  1540.         ^self changed: #getList
  1541.     ].
  1542.     super update: aSymbol! !
  1543.  
  1544. !AbstractScoreEvent methodsFor: 'accessing' stamp: 'di 6/17/1999 14:28'!
  1545. adjustTimeBy: delta
  1546.  
  1547.     time _ time + delta
  1548. ! !
  1549.  
  1550. !AbstractScoreEvent methodsFor: 'accessing' stamp: 'jm 8/27/1998 16:38'!
  1551. endTime
  1552.     "Subclasses should override to return the ending time if the event has some duration."
  1553.  
  1554.     ^ time
  1555. ! !
  1556.  
  1557. !AbstractScoreEvent methodsFor: 'classification' stamp: 'jm 9/10/1998 09:43'!
  1558. isControlChange
  1559.  
  1560.     ^ false
  1561. ! !
  1562.  
  1563. !AbstractScoreEvent methodsFor: 'classification' stamp: 'jm 9/10/1998 09:43'!
  1564. isPitchBend
  1565.  
  1566.     ^ false
  1567. ! !
  1568.  
  1569. !AbstractScoreEvent methodsFor: 'classification' stamp: 'jm 9/10/1998 09:43'!
  1570. isProgramChange
  1571.  
  1572.     ^ false
  1573. ! !
  1574.  
  1575. !AbstractScoreEvent methodsFor: 'midi' stamp: 'jm 9/10/1998 18:31'!
  1576. outputOnMidiPort: aMidiPort
  1577.     "Output this event to the given MIDI port. This default implementation does nothing."
  1578. ! !
  1579.  
  1580. !AbstractSound methodsFor: 'initialization' stamp: 'jm 3/24/1999 12:03'!
  1581. loudness: aNumber
  1582.     "Initialize my volume envelopes and initial volume. Subclasses overriding this method should include a resend to super."
  1583.  
  1584.     | vol |
  1585.     vol _ (aNumber asFloat max: 0.0) min: 1.0.
  1586.     envelopes do: [:e |
  1587.         (e isKindOf: VolumeEnvelope) ifTrue: [e scale: vol]].
  1588.     self initialVolume: vol.
  1589. ! !
  1590.  
  1591. !AbstractSound methodsFor: 'initialization' stamp: 'jm 7/6/1998 17:04'!
  1592. nameOrNumberToPitch: aStringOrNumber
  1593.     "Answer the pitch in cycles/second for the given pitch specification. The specification can be either a numeric pitch or pitch name such as 'c4'."
  1594.  
  1595.     aStringOrNumber isNumber
  1596.         ifTrue: [^ aStringOrNumber asFloat]
  1597.         ifFalse: [^ AbstractSound pitchForName: aStringOrNumber]
  1598. ! !
  1599.  
  1600. !AbstractSound methodsFor: 'initialization' stamp: 'jm 8/19/1998 08:45'!
  1601. setPitch: pitchNameOrNumber dur: d loudness: l
  1602.     "Initialize my envelopes for the given parameters. Subclasses overriding this method should include a resend to super."
  1603.  
  1604.     | p |
  1605.     p _ self nameOrNumberToPitch: pitchNameOrNumber.
  1606.     envelopes do: [:e |
  1607.         e volume: l.
  1608.         e centerPitch: p].
  1609.     self initialVolume: l.
  1610.     self duration: d.
  1611. ! !
  1612.  
  1613. !AbstractSound methodsFor: 'initialization' stamp: 'jm 8/3/1998 17:11'!
  1614. soundForMidiKey: midiKey dur: d loudness: l
  1615.     "Answer an initialized sound object (a copy of the receiver) that generates a note for the given MIDI key (in the range 0..127), duration (in seconds), and loudness (in the range 0.0 to 1.0)."
  1616.  
  1617.     ^ self copy
  1618.         setPitch: (AbstractSound pitchForMIDIKey: midiKey)
  1619.         dur: d
  1620.         loudness: l
  1621. ! !
  1622.  
  1623. !AbstractSound methodsFor: 'initialization' stamp: 'jm 8/3/1998 16:58'!
  1624. soundForPitch: pitchNameOrNumber dur: d loudness: l
  1625.     "Answer an initialized sound object (a copy of the receiver) that generates a note of the given pitch, duration, and loudness. Pitch may be a numeric pitch or a string pitch name such as 'c4'. Duration is in seconds and loudness is in the range 0.0 to 1.0."
  1626.  
  1627.     ^ self copy setPitch: pitchNameOrNumber dur: d loudness: l
  1628. ! !
  1629.  
  1630. !AbstractSound methodsFor: 'envelopes' stamp: 'jm 8/18/1998 09:57'!
  1631. removeAllEnvelopes
  1632.     "Remove all envelopes from my envelopes list."
  1633.  
  1634.     envelopes _ #().
  1635. ! !
  1636.  
  1637. !AbstractSound methodsFor: 'volume' stamp: 'jm 8/13/1998 16:37'!
  1638. loudness
  1639.     "Answer the current volume setting for this sound."
  1640.  
  1641.     ^ scaledVol asFloat / ScaleFactor asFloat! !
  1642.  
  1643. !AbstractSound methodsFor: 'volume' stamp: 'jm 8/13/1998 16:28'!
  1644. volumeEnvelopeScaledTo: scalePoint
  1645.     "Return a collection of values representing my volume envelope scaled by the given point. The scale point's x component is pixels/second and its y component is the number of pixels for full volume."
  1646.  
  1647.     self error: 'not yet implemented'.
  1648. ! !
  1649.  
  1650. !AbstractSound methodsFor: 'playing' stamp: 'ar 12/5/1998 22:20'!
  1651. isPlaying
  1652.     "Return true if the receiver is currently playing"
  1653.     ^ SoundPlayer isPlaying: self! !
  1654.  
  1655. !AbstractSound methodsFor: 'playing' stamp: 'di 5/30/1999 12:46'!
  1656. millisecondsSinceStart
  1657.  
  1658.     ^ mSecsSinceStart! !
  1659.  
  1660. !AbstractSound methodsFor: 'playing' stamp: 'jm 8/13/1998 15:09'!
  1661. playAndWaitUntilDone
  1662.     "Play this sound to the sound ouput port and wait until it has finished playing before returning."
  1663.  
  1664.     SoundPlayer playSound: self.
  1665.     [self samplesRemaining > 0] whileTrue.
  1666.     (Delay forMilliseconds: 2 * SoundPlayer bufferMSecs) wait.  "ensure last buffer has been output"
  1667. ! !
  1668.  
  1669. !AbstractSound methodsFor: 'playing' stamp: 'jm 8/18/1998 10:52'!
  1670. playChromaticRunFrom: startPitch to: endPitch
  1671.     "Play a fast chromatic run between the given pitches. Useful for auditioning a sound."
  1672.  
  1673.     (AbstractSound chromaticRunFrom: startPitch to: endPitch on: self) play.
  1674. ! !
  1675.  
  1676. !AbstractSound methodsFor: 'playing' stamp: 'jm 8/13/1998 16:17'!
  1677. playSampleCount: n into: aSoundBuffer startingAt: startIndex
  1678.     "Mix the next n samples of this sound into the given buffer starting at the given index. Update the receiver's control parameters periodically."
  1679.  
  1680.     | fullVol samplesBetweenControlUpdates pastEnd i remainingSamples count |
  1681.     fullVol _ AbstractSound scaleFactor.
  1682.     samplesBetweenControlUpdates _ self samplingRate // self controlRate.
  1683.     pastEnd _ startIndex + n.  "index just after the last sample"
  1684.     i _ startIndex.
  1685.     [i < pastEnd] whileTrue: [
  1686.         remainingSamples _ self samplesRemaining.
  1687.         remainingSamples <= 0 ifTrue: [^ self].
  1688.         count _ pastEnd - i.
  1689.         samplesUntilNextControl < count ifTrue: [count _ samplesUntilNextControl].
  1690.         remainingSamples < count ifTrue: [count _ remainingSamples].
  1691.         self mixSampleCount: count into: aSoundBuffer startingAt: i leftVol: fullVol rightVol: fullVol.
  1692.         samplesUntilNextControl _ samplesUntilNextControl - count.
  1693.         samplesUntilNextControl <= 0 ifTrue: [
  1694.             self doControl.
  1695.             samplesUntilNextControl _ samplesBetweenControlUpdates].
  1696.         i _ i + count].
  1697. ! !
  1698.  
  1699. !AbstractSound methodsFor: 'playing' stamp: 'jm 7/5/1998 17:53'!
  1700. playSilently
  1701.     "Compute the samples of this sound without outputting them. Used for performance analysis."
  1702.  
  1703.     | bufSize buf |
  1704.     self reset.
  1705.     bufSize _ self samplingRate // 10.
  1706.     buf _ SoundBuffer newStereoSampleCount: bufSize.
  1707.     [self samplesRemaining > 0] whileTrue: [
  1708.         buf primFill: 0.
  1709.         self playSampleCount: bufSize into: buf startingAt: 1].
  1710. ! !
  1711.  
  1712. !AbstractSound methodsFor: 'playing' stamp: 'jm 8/19/1998 08:30'!
  1713. viewSamples
  1714.  
  1715.     | stereoBuf |
  1716.     stereoBuf _ self computeSamplesForSeconds: self duration.
  1717.     WaveEditor openOn: stereoBuf extractLeftChannel.
  1718. ! !
  1719.  
  1720. !AbstractSound methodsFor: 'sound generation' stamp: 'jm 8/17/1998 13:34'!
  1721. doControl
  1722.     "Update the control parameters of this sound using its envelopes, if any."
  1723.     "Note: This is only called at a small fraction of the sampling rate."
  1724.  
  1725.     | pitchModOrRatioChange |
  1726.     envelopes size > 0 ifTrue: [
  1727.         pitchModOrRatioChange _ false.
  1728.         1 to: envelopes size do: [:i |
  1729.             ((envelopes at: i) updateTargetAt: mSecsSinceStart)
  1730.                 ifTrue: [pitchModOrRatioChange _ true]].
  1731.         pitchModOrRatioChange ifTrue: [self internalizeModulationAndRatio]].
  1732.     mSecsSinceStart _ mSecsSinceStart + (1000 // self controlRate).
  1733. ! !
  1734.  
  1735. !AbstractSound methodsFor: 'sound generation' stamp: 'jm 7/6/1998 06:40'!
  1736. mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol
  1737.     "Mix the given number of samples with the samples already in the given buffer starting at the given index. Assume that the buffer size is at least (index + count) - 1. The leftVol and rightVol parameters determine the volume of the sound in each channel, where 0 is silence and ScaleFactor is full volume."
  1738.  
  1739.     self subclassResponsibility.
  1740. ! !
  1741.  
  1742. !AbstractSound methodsFor: 'sound generation' stamp: 'jm 8/17/1998 13:45'!
  1743. reset
  1744.     "Reset my internal state for a replay. Methods that override this method should do super reset."
  1745.  
  1746.     mSecsSinceStart _ 0.
  1747.     samplesUntilNextControl _ 0.
  1748.     envelopes size > 0 ifTrue: [
  1749.         1 to: envelopes size do: [:i | (envelopes at: i) reset]].
  1750. ! !
  1751.  
  1752. !AbstractSound methodsFor: 'sound generation' stamp: 'jm 9/9/1998 21:56'!
  1753. stopAfterMSecs: mSecs
  1754.     "Terminate this sound this note after the given number of milliseconds. This default implementation does nothing."
  1755. ! !
  1756.  
  1757. !AbstractSound methodsFor: 'sound generation' stamp: 'jm 9/9/1998 21:54'!
  1758. stopGracefully
  1759.     "End this note with a graceful decay. If the note has envelopes, determine the decay time from its envelopes."
  1760.  
  1761.     | decayInMs env |
  1762.     envelopes isEmpty
  1763.         ifTrue: [
  1764.             self adjustVolumeTo: 0 overMSecs: 10.
  1765.             decayInMs _ 10]
  1766.         ifFalse: [
  1767.             env _ envelopes first.
  1768.             decayInMs _ env attackTime + env decayTime].
  1769.     self duration: (mSecsSinceStart + decayInMs) / 1000.0.
  1770.     self stopAfterMSecs: decayInMs.
  1771. ! !
  1772.  
  1773. !AbstractSound methodsFor: 'composition' stamp: 'jm 2/2/1999 15:53'!
  1774. asSound
  1775.  
  1776.     ^ self
  1777. ! !
  1778.  
  1779. !AbstractSound methodsFor: 'copying' stamp: 'di 3/4/1999 21:29'!
  1780. sounds
  1781.     "Allows simple sounds to behave as, eg, sequential sounds"
  1782.  
  1783.     ^ Array with: self! !
  1784.  
  1785. !AbstractSound methodsFor: 'file i/o' stamp: 'jm 3/13/1999 11:47'!
  1786. storeAIFFOnFileNamed: fileName
  1787.  
  1788.     | f |
  1789.     f _ (FileStream fileNamed: fileName) binary.
  1790.     self storeAIFFSamples: self samples samplingRate: self originalSamplingRate on: f.
  1791.     f close.
  1792. ! !
  1793.  
  1794. !AbstractSound methodsFor: 'file i/o' stamp: 'jm 3/13/1999 11:48'!
  1795. storeAIFFSamples: aSoundBuffer samplingRate: rate on: aBinaryStream
  1796.  
  1797.     | sampleCount s |
  1798.     sampleCount _ aSoundBuffer monoSampleCount.
  1799.     aBinaryStream nextPutAll: 'FORM' asByteArray.
  1800.     aBinaryStream nextInt32Put: (2 * sampleCount) + ((7 * 4) + 18).
  1801.     aBinaryStream nextPutAll: 'AIFF' asByteArray.
  1802.     aBinaryStream nextPutAll: 'COMM' asByteArray.
  1803.     aBinaryStream nextInt32Put: 18.
  1804.     aBinaryStream nextNumber: 2 put: 1.  "channels"
  1805.     aBinaryStream nextInt32Put: sampleCount.
  1806.     aBinaryStream nextNumber: 2 put: 16.  "bits/sample"
  1807.     self storeExtendedFloat: rate on: aBinaryStream.
  1808.     aBinaryStream nextPutAll: 'SSND' asByteArray.
  1809.     aBinaryStream nextInt32Put: (2 * sampleCount) + 8.
  1810.     aBinaryStream nextInt32Put: 0.
  1811.     aBinaryStream nextInt32Put: 0.
  1812.     1 to: sampleCount do: [:i |
  1813.         s _ aSoundBuffer at: i.
  1814.         aBinaryStream nextPut: ((s bitShift: -8) bitAnd: 16rFF).
  1815.         aBinaryStream nextPut: (s bitAnd: 16rFF)].
  1816. ! !
  1817.  
  1818. !AbstractSound methodsFor: 'file i/o' stamp: 'jm 3/13/1999 11:34'!
  1819. storeExtendedFloat: aNumber on: aBinaryStream
  1820.     "Store an Apple extended-precision 80-bit floating point number on the given stream."
  1821.     "Details: I could not find the specification for this format, so constants were determined empirically based on assumption of 1-bit sign, 15-bit exponent, 64-bit mantissa. This format does not seem to have an implicit one before the mantissa as some float formats do."
  1822.  
  1823.     | n isNeg exp mantissa |
  1824.     n _ aNumber asFloat.
  1825.     isNeg _ false.
  1826.     n < 0.0 ifTrue: [
  1827.         n _ 0.0 - n.
  1828.         isNeg _ true].
  1829.     exp _ (n log: 2.0) ceiling.
  1830.     mantissa _ (n * (2 raisedTo: 64 - exp)) truncated.
  1831.     exp _ exp + 16r4000 - 2.  "not sure why the -2 is needed..."
  1832.     isNeg ifTrue: [exp _ exp bitOr: 16r8000].  "set sign bit"
  1833.     aBinaryStream nextPut: ((exp bitShift: -8) bitAnd: 16rFF).
  1834.     aBinaryStream nextPut: (exp bitAnd: 16rFF).
  1835.     8 to: 1 by: -1 do: [:i | aBinaryStream nextPut: (mantissa digitAt: i)].
  1836. ! !
  1837.  
  1838. !AbstractSound methodsFor: 'conversion' stamp: 'mjg 12/3/1999 12:58'!
  1839. asSampledSound
  1840.     ^SampledSound samples: (self computeSamplesForSeconds: self 
  1841. duration) samplingRate: (self samplingRate)*2.
  1842. ! !
  1843.  
  1844. !AbstractSound class methodsFor: 'class initialization' stamp: 'jm 8/3/1998 16:13'!
  1845. initialize
  1846.     "AbstractSound initialize"
  1847.  
  1848.     | bottomC |
  1849.     ScaleFactor _ 2 raisedTo: 15.
  1850.     FloatScaleFactor _ ScaleFactor asFloat.
  1851.     MaxScaledValue _ ((2 raisedTo: 31) // ScaleFactor) - 1.  "magnitude of largest scaled value in 32-bits"
  1852.  
  1853.     "generate pitches for c-1 through c0"
  1854.     bottomC _ (440.0 / 32) * (2.0 raisedTo: -9.0 / 12.0).
  1855.     PitchesForBottomOctave _ (0 to: 12) collect: [:i | bottomC * (2.0 raisedTo: i asFloat / 12.0)].
  1856.     TopOfBottomOctave _ PitchesForBottomOctave last.
  1857. ! !
  1858.  
  1859. !AbstractSound class methodsFor: 'instance creation' stamp: 'jm 8/3/1998 17:00'!
  1860. noteSequenceOn: aSound from: anArray
  1861.     "Build a note sequence (i.e., a SequentialSound) from the given array using the given sound as the instrument. Elements are either (pitch, duration, loudness) triples or (#rest duration) pairs.  Pitches can be given as names or as numbers."
  1862.     | score pitch |
  1863.     score _ SequentialSound new.
  1864.     anArray do: [:el |
  1865.         el size = 3
  1866.             ifTrue: [
  1867.                 pitch _ el at: 1.
  1868.                 pitch isNumber ifFalse: [pitch _ self pitchForName: pitch].
  1869.                 score add: (
  1870.                     aSound
  1871.                         soundForPitch: pitch
  1872.                         dur: (el at: 2)
  1873.                         loudness: (el at: 3) / 1000.0)]
  1874.             ifFalse: [
  1875.                 score add: (RestSound dur: (el at: 2))]].
  1876.     ^ score
  1877. ! !
  1878.  
  1879. !AbstractSound class methodsFor: 'utilities' stamp: 'jm 8/3/1998 16:16'!
  1880. indexOfBottomOctavePitch: p
  1881.     "Answer the index of the first pitch in the bottom octave equal to or higher than the given pitch. Assume that the given pitch is below the top pitch of the bottom octave."
  1882.  
  1883.     1 to: PitchesForBottomOctave size do: [:i |
  1884.         (PitchesForBottomOctave at: i) >= p ifTrue: [^ i]].
  1885.     self error: 'implementation error: argument pitch should be below or within the bottom octave'.
  1886. ! !
  1887.  
  1888. !AbstractSound class methodsFor: 'utilities' stamp: 'jm 8/3/1998 16:16'!
  1889. midiKeyForPitch: pitchNameOrNumber
  1890.     "Answer the midiKey closest to the given pitch. Pitch may be a numeric pitch or a pitch name string such as 'c4'."
  1891.     "AbstractSound midiKeyForPitch: 440.0"
  1892.  
  1893.     | p octave i midiKey |
  1894.     pitchNameOrNumber isNumber
  1895.         ifTrue: [p _ pitchNameOrNumber asFloat]
  1896.         ifFalse: [p _ AbstractSound pitchForName: pitchNameOrNumber].
  1897.     octave _ -1.
  1898.     [p >= TopOfBottomOctave] whileTrue: [
  1899.         octave _ octave + 1.
  1900.         p _ p / 2.0].
  1901.  
  1902.     i _ self indexOfBottomOctavePitch: p.
  1903.     (i > 1) ifTrue: [
  1904.         (p - (PitchesForBottomOctave at: i - 1)) < ((PitchesForBottomOctave at: i) - p)
  1905.             ifTrue: [i _ i - 1]].
  1906.  
  1907.     midiKey _ ((octave * 12) + 11 + i).
  1908.     midiKey > 127 ifTrue: [midiKey _ 127].
  1909.     ^ midiKey
  1910. ! !
  1911.  
  1912. !AbstractSound class methodsFor: 'utilities' stamp: 'jm 8/3/1998 16:43'!
  1913. pitchForMIDIKey: midiKey
  1914.     "Answer the pitch for the given MIDI key."
  1915.     "(1 to: 127) collect: [:i | AbstractSound pitchForMIDIKey: i]"
  1916.  
  1917.     | indexInOctave octave |
  1918.     indexInOctave _ (midiKey \\ 12) + 1.
  1919.     octave _ (midiKey // 12) + 1.
  1920.     ^ (PitchesForBottomOctave at: indexInOctave) *
  1921.         (#(1.0 2.0 4.0 8.0 16.0 32.0 64.0 128.0 256.0 512.0 1024.0) at: octave)
  1922. ! !
  1923.  
  1924. !AbstractSound class methodsFor: 'utilities' stamp: 'jm 7/6/1998 15:47'!
  1925. pitchTable
  1926.     "AbstractSound pitchTable"
  1927.  
  1928.     | out note i |
  1929.     out _ WriteStream on: (String new: 1000).
  1930.     i _ 12.
  1931.     0 to: 8 do: [:octave |
  1932.         #(c 'c#' d eb e f fs g 'g#' a bf b) do: [:noteName |
  1933.             note _ noteName, octave printString.
  1934.             out nextPutAll: note; tab.
  1935.             out nextPutAll: i printString; tab.
  1936.             out nextPutAll: (AbstractSound pitchForName: note) printString; cr.
  1937.             i _ i + 1]].
  1938.     ^ out contents
  1939. ! !
  1940.  
  1941. !AbstractSound class methodsFor: 'examples' stamp: 'jm 6/30/1998 18:40'!
  1942. chromaticPitchesFrom: aPitch
  1943.  
  1944.     | halfStep pitch |
  1945.     halfStep _ 2.0 raisedTo: (1.0 / 12.0).
  1946.     pitch _ aPitch isNumber
  1947.             ifTrue: [aPitch]
  1948.             ifFalse: [self pitchForName: aPitch].
  1949.     pitch _ pitch / halfStep.
  1950.     ^ (0 to: 14) collect: [:i | pitch _ pitch * halfStep]
  1951. ! !
  1952.  
  1953. !AbstractSound class methodsFor: 'examples' stamp: 'jm 8/18/1998 11:32'!
  1954. chromaticRunFrom: startPitch to: endPitch on: aSound
  1955.     "Answer a composite sound consisting of a rapid chromatic run between the given pitches on the given sound."
  1956.     "(AbstractSound chromaticRunFrom: 'c3' to: 'c#5' on: FMSound oboe1) play"
  1957.  
  1958.     | scale halfStep pEnd p |
  1959.     scale _ SequentialSound new.
  1960.     halfStep _ 2.0 raisedTo: (1.0 / 12.0).
  1961.     endPitch isNumber
  1962.         ifTrue: [pEnd _ endPitch asFloat]
  1963.         ifFalse: [pEnd _ AbstractSound pitchForName: endPitch].
  1964.     startPitch isNumber
  1965.         ifTrue: [p _ startPitch asFloat]
  1966.         ifFalse: [p _ AbstractSound pitchForName: startPitch].
  1967.     [p <= pEnd] whileTrue: [
  1968.         scale add: (aSound soundForPitch: p dur: 0.2 loudness: 0.5).
  1969.         p _ p * halfStep].
  1970.     ^ scale
  1971. ! !
  1972.  
  1973. !AbstractSound class methodsFor: 'examples' stamp: 'jm 8/3/1998 17:00'!
  1974. majorChordOn: aSound from: aPitch
  1975.     "FMSound majorChord play"
  1976.  
  1977.     | score majorScale leadingRest pan note |
  1978.     majorScale _ self majorPitchesFrom: aPitch.
  1979.     score _ MixedSound new.
  1980.     leadingRest _ pan _ 0.
  1981.     #(1 3 5 8) do: [:noteIndex |
  1982.         note _ aSound
  1983.             soundForPitch: (majorScale at: noteIndex)
  1984.             dur: 2.0 - leadingRest
  1985.             loudness: 0.3.
  1986.         score add: (RestSound dur: leadingRest), note pan: pan.
  1987.         leadingRest _ leadingRest + 0.2.
  1988.         pan _ pan + 0.3].
  1989.     ^ score
  1990. ! !
  1991.  
  1992. !AbstractSound class methodsFor: 'examples' stamp: 'jm 7/13/1998 13:09'!
  1993. majorScaleOn: aSound from: aPitch
  1994.     "FMSound majorScale play"
  1995.  
  1996.     ^ self noteSequenceOn: aSound
  1997.         from: ((self majorPitchesFrom: aPitch)
  1998.              collect: [:pitch | Array with: pitch with: 0.5 with: 300])
  1999. ! !
  2000.  
  2001. !AbstractSound class methodsFor: 'examples' stamp: 'jm 1/4/1999 09:26'!
  2002. majorScaleOn: aSound from: aPitch octaves: octaveCount
  2003.     "(AbstractSound majorScaleOn: FMSound oboe1 from: #c2 octaves: 5) play"
  2004.  
  2005.     | startingPitch pitches chromatic |
  2006.     startingPitch _ aPitch isNumber
  2007.         ifTrue: [aPitch]
  2008.         ifFalse: [self pitchForName: aPitch].
  2009.     pitches _ OrderedCollection new.
  2010.     0 to: octaveCount - 1 do: [:i |
  2011.         chromatic _ self chromaticPitchesFrom: startingPitch * (2 raisedTo: i).
  2012.         #(1 3 5 6 8 10 12) do: [:j | pitches addLast: (chromatic at: j)]].
  2013.     pitches addLast: startingPitch * (2 raisedTo: octaveCount).
  2014.     ^ self noteSequenceOn: aSound
  2015.         from: (pitches collect: [:pitch | Array with: pitch with: 0.5 with: 300])
  2016. ! !
  2017.  
  2018. !AbstractSound class methodsFor: 'examples' stamp: 'di 4/13/1999 13:53'!
  2019. testFMInteractively
  2020.     "Experiment with different settings of the FM modulation and multiplier settings interactively by moving the mouse. The top-left corner of the screen is 0 for both parameters. Stop when the mouse is pressed."
  2021.     "AbstractSound testFMInteractively"
  2022.  
  2023.     | s mousePt lastVal status mod ratio |
  2024.     SoundPlayer startPlayerProcessBufferSize: 1100 rate: 11025 stereo: false.
  2025.     s _ FMSound pitch: 440.0 dur: 200.0 loudness: 0.2.
  2026.  
  2027.     SoundPlayer playSound: s.
  2028.     lastVal _ nil.
  2029.     [Sensor anyButtonPressed] whileFalse: [
  2030.         mousePt _ Sensor cursorPoint.
  2031.         mousePt ~= lastVal ifTrue: [
  2032.             mod _ mousePt x asFloat / 20.0.
  2033.             ratio _ mousePt y asFloat / 20.0.
  2034.             s modulation: mod ratio: ratio.
  2035.             lastVal _ mousePt.
  2036.             status _
  2037. 'mod: ', mod printString, '
  2038. ratio: ', ratio printString.
  2039.             status displayOn: Display at: 10@10]].
  2040.  
  2041.     SoundPlayer shutDown.
  2042. ! !
  2043.  
  2044. !AbstractSound class methodsFor: 'sound library' stamp: 'jm 8/14/1998 13:27'!
  2045. initSounds
  2046.     "AbstractSound initSounds"
  2047.  
  2048.     Sounds _ Dictionary new.
  2049.     (FMSound class organization listAtCategoryNamed: #instruments)
  2050.         do: [:sel | Sounds at: sel asString put: (FMSound perform: sel)].
  2051. ! !
  2052.  
  2053. !AbstractSound class methodsFor: 'sound library' stamp: 'jm 8/14/1998 13:25'!
  2054. soundNamed: soundName
  2055.  
  2056.     ^ Sounds at: soundName
  2057. ! !
  2058.  
  2059. !AbstractSound class methodsFor: 'sound library' stamp: 'tk 6/24/1999 11:31'!
  2060. soundNamed: soundName put: aSound
  2061.  
  2062.     Sounds at: soundName put: aSound.
  2063.     Smalltalk at: #ScorePlayerMorph ifPresent: [:playerClass |
  2064.         playerClass allSubInstancesDo:
  2065.             [:player | player updateInstrumentsFromLibrary]].
  2066. ! !
  2067.  
  2068. !AbstractSound class methodsFor: 'sound library' stamp: 'jm 8/19/1998 14:11'!
  2069. soundNames
  2070.  
  2071.     ^ Sounds keys asSortedCollection asArray
  2072. ! !
  2073.  
  2074. !AbstractSound class methodsFor: 'sound library' stamp: 'jm 8/4/1998 18:26'!
  2075. sounds
  2076.  
  2077.     ^ Sounds
  2078. ! !
  2079.  
  2080. !AbstractSound class methodsFor: 'sound library' stamp: 'jm 1/14/1999 13:00'!
  2081. updateFMSounds
  2082.     "AbstractSound updateFMSounds"
  2083.  
  2084.     Sounds keys do: [:k |
  2085.         ((Sounds at: k) isKindOf: FMSound) ifTrue: [
  2086.             Sounds removeKey: k ifAbsent: []]].
  2087.  
  2088.     (FMSound class organization listAtCategoryNamed: #instruments) do:
  2089.         [:sel | Sounds at: sel asString put: (FMSound perform: sel)].
  2090. ! !
  2091.  
  2092. !AbstractSound class methodsFor: 'sound library-file in/out' stamp: 'sge 2/13/2000 05:20'!
  2093. fileInSoundLibrary
  2094.     "Prompt the user for a file name and the file in the sound library with that name."
  2095.     "AbstractSound fileInSoundLibrary"
  2096.  
  2097.     | fileName |
  2098.     fileName _ FillInTheBlank request: 'Sound library file name?'.
  2099.     fileName isEmptyOrNil ifTrue: [^ self].
  2100.     (fileName endsWith: '.sounds') ifFalse: [fileName _ fileName, '.sounds'].
  2101.     self fileInSoundLibraryNamed: fileName.
  2102. ! !
  2103.  
  2104. !AbstractSound class methodsFor: 'sound library-file in/out' stamp: 'tk 6/24/1999 07:20'!
  2105. fileInSoundLibraryNamed: fileName
  2106.     "File in the sound library with the given file name, and add its contents to the current sound library."
  2107.  
  2108.     | s newSounds |
  2109.     s _ FileStream oldFileNamed: fileName.
  2110.     newSounds _ s fileInObjectAndCode.
  2111.     s close.
  2112.     newSounds associationsDo:
  2113.         [:assoc | self storeFiledInSound: assoc value named: assoc key].
  2114.     ScorePlayerMorph allSubInstances do: [:p | p updateInstrumentsFromLibrary].
  2115.     Smalltalk garbageCollect.
  2116. ! !
  2117.  
  2118. !AbstractSound class methodsFor: 'sound library-file in/out' stamp: 'jm 8/19/1998 12:42'!
  2119. fileOutSoundLibrary
  2120.     "File out the current sound library."
  2121.     "AbstractSound fileOutSoundLibrary"
  2122.  
  2123.     self fileOutSoundLibrary: Sounds.
  2124. ! !
  2125.  
  2126. !AbstractSound class methodsFor: 'sound library-file in/out' stamp: 'sge 2/13/2000 05:22'!
  2127. fileOutSoundLibrary: aDictionary
  2128.     "File out the given dictionary, which is assumed to contain sound and instrument objects keyed by their names."
  2129.     "Note: This method is separated out so that one can file out edited sound libraries, as well as the system sound library. To make such a collection, you can inspect AbstractSound sounds and remove the items you don't want. Then do: 'AbstractSound fileOutSoundLibrary: self' from the Dictionary inspector."
  2130.  
  2131.     | fileName refStream |
  2132.     (aDictionary isKindOf: Dictionary)
  2133.         ifFalse: [self error: 'arg should be a dictionary of sounds'].
  2134.     fileName _ FillInTheBlank request: 'Sound library file name?'.
  2135.     fileName isEmptyOrNil ifTrue: [^ self].
  2136.     refStream _ SmartRefStream fileNamed: fileName, '.sounds'.
  2137.     refStream nextPut: aDictionary.
  2138.     refStream close.
  2139. ! !
  2140.  
  2141. !AbstractSound class methodsFor: 'sound library-file in/out' stamp: 'jm 9/12/1998 21:35'!
  2142. storeFiledInSound: snd named: sndName
  2143.     "Store the given sound in the sound library. Use the given name if it isn't in use, otherwise ask the user what to do."
  2144.  
  2145.     | menu choice i |
  2146.     (Sounds includesKey: sndName) ifFalse: [  "no name clash"
  2147.         Sounds at: sndName put: snd.
  2148.         ^ self].
  2149.  
  2150.     (Sounds at: sndName) == UnloadedSnd ifTrue: [
  2151.         "re-loading a sound that was unloaded to save space"
  2152.         Sounds at: sndName put: snd.
  2153.         ^ self].
  2154.  
  2155.     "the given sound name is already used"
  2156.     menu _ SelectionMenu selections:
  2157.         #('replace the existing sound' 'rename the new sound' 'skip it').
  2158.     choice _ menu startUpWithCaption:
  2159.         '"', sndName, '" has the same name as an existing sound'.
  2160.     (choice beginsWith: 'replace') ifTrue: [
  2161.         Sounds at: sndName put: snd.
  2162.         ^ self].
  2163.     (choice beginsWith: 'rename') ifTrue: [
  2164.         i _ 2.
  2165.         [Sounds includesKey: (sndName, ' v', i printString)] whileTrue: [i _ i + 1].
  2166.         Sounds at: (sndName, ' v', i printString) put: snd].
  2167. ! !
  2168.  
  2169. !AbstractSound class methodsFor: 'sound library-file in/out' stamp: 'jm 9/12/1998 22:18'!
  2170. unloadSampledTimbres
  2171.     "This can be done to unload those bulky sampled timbres to shrink the image. The unloaded sounds are replaced by a well-known 'unloaded sound' object to enable the unloaded sounds to be detected when the process is reversed."
  2172.     "AbstractSound unloadSampledTimbres"
  2173.  
  2174.     Sounds keys copy do: [:soundName |
  2175.         (((Sounds at: soundName) isKindOf: SampledInstrument) or:
  2176.          [(Sounds at: soundName) isKindOf: LoopedSampledSound]) ifTrue: [
  2177.             Sounds at: soundName put: self unloadedSound]].
  2178.     self updateScorePlayers.
  2179.     Smalltalk garbageCollect.
  2180. ! !
  2181.  
  2182. !AbstractSound class methodsFor: 'sound library-file in/out' stamp: 'jm 9/11/1998 16:47'!
  2183. unloadSoundNamed: soundName
  2184.  
  2185.     (Sounds includesKey: soundName) ifTrue: [
  2186.         Sounds at: soundName put: self unloadedSound].
  2187.     self updateScorePlayers.
  2188. ! !
  2189.  
  2190. !AbstractSound class methodsFor: 'sound library-file in/out' stamp: 'jm 9/12/1998 21:48'!
  2191. unloadedSound
  2192.     "Answer a sound to be used as the place-holder for sounds that have been unloaded."
  2193.  
  2194.     UnloadedSnd ifNil: [UnloadedSnd _ UnloadedSound default copy].
  2195.     ^ UnloadedSnd
  2196. ! !
  2197.  
  2198. !AbstractSound class methodsFor: 'sound library-file in/out' stamp: 'tk 6/24/1999 07:20'!
  2199. updateScorePlayers
  2200.     "Force all ScorePlayers to update their instrument list from the sound library. This may done after loading, unloading, or replacing a sound to make all ScorePlayers feel the change."
  2201.  
  2202.     ScorePlayer allSubInstances do: [:p | p pause].
  2203.     SoundPlayer shutDown.
  2204.     ScorePlayerMorph allInstances do: [:p | p updateInstrumentsFromLibrary].
  2205. ! !
  2206.  
  2207. !AbstractSound class methodsFor: 'primitive generation' stamp: 'jm 8/19/1998 14:22'!
  2208. cCodeForSoundPrimitives
  2209.     "Return a string containing the C code for the sound primitives. This string is pasted into a file, compiled, and linked into the virtual machine. Note that the virtual machine's primitive table must also be edited to make new primitives available."
  2210.     "AbstractSound cCodeForSoundPrimitives"
  2211.  
  2212.     ^ CCodeGenerator new codeStringForPrimitives: #(
  2213.         (FMSound mixSampleCount:into:startingAt:leftVol:rightVol:)
  2214.         (PluckedSound mixSampleCount:into:startingAt:leftVol:rightVol:)
  2215.         (LoopedSampledSound mixSampleCount:into:startingAt:leftVol:rightVol:)
  2216.         (SampledSound mixSampleCount:into:startingAt:leftVol:rightVol:)
  2217.         (ReverbSound applyReverbTo:startingAt:count:)
  2218.     ).
  2219. ! !
  2220.  
  2221. !AcceptableCleanTextMorph methodsFor: 'as yet unclassified' stamp: 'di 6/22/1998 21:38'!
  2222. accept
  2223.     "Overridden to allow accept of clean text"
  2224.     | textToAccept ok |
  2225.     textToAccept _ textMorph asText.
  2226.     ok _ (setTextSelector == nil) or:
  2227.         [setTextSelector numArgs = 2
  2228.             ifTrue: [model perform: setTextSelector with: textToAccept with: self]
  2229.             ifFalse: [model perform: setTextSelector with: textToAccept]].
  2230.     ok ifTrue:
  2231.         [self setText: self getText.
  2232.         self hasUnacceptedEdits: false]! !
  2233.  
  2234. !AcornFileDirectory methodsFor: 'file name utilities' stamp: 'ar 12/18/1999 00:47'!
  2235. fullPathFor: path
  2236.     path isEmpty ifTrue:[^pathName].
  2237.     ((path includes: $$ ) or:[path includes: $:]) ifTrue:[^path].
  2238.     ^pathName, self slash, path! !
  2239.  
  2240. !AcornFileDirectory class methodsFor: 'platform specific' stamp: 'TPR 5/12/1998 22:48'!
  2241. isActiveDirectoryClass
  2242.     "Does this class claim to be that properly active subclass of FileDirectory for this platform?
  2243.     On Acorn, the test is whether systemAttribute 1001 = 'RiscOS' (on newer VMs) or if the primPathNameDelimiter is $. (on older ones), which is what we would like to use for a dirsep if only it would work out. See pathNameDelimiter for more woeful details - then just get on and enjoy Squeak"
  2244.     | attr |
  2245.     attr _ Smalltalk getSystemAttribute: 1001.
  2246.     attr isNil ifFalse:[^attr = 'RiscOS'].
  2247.     ^self primPathNameDelimiter = $.
  2248. ! !
  2249.  
  2250. !AcornFileDirectory class methodsFor: 'platform specific' stamp: 'TPR 7/20/1999 17:52'!
  2251. maxFileNameLength
  2252.  
  2253.     ^ 255
  2254. ! !
  2255.  
  2256. !AcornFileDirectory class methodsFor: 'platform specific' stamp: 'TPR 5/10/1998 21:45'!
  2257. pathNameDelimiter
  2258. "Acorn RiscOS uses a dot as the directory separator and has no real concept of filename extensions. We tried to make code handle this, but there are just too many uses of dot as a filename extension - so fake it out by pretending to use a slash. The file prims do conversions instead.
  2259. Sad, but pragmatic"
  2260.     ^ $/
  2261. ! !
  2262.  
  2263. This class implements Actions for Wonderlands. An Action is some task that should be executed every frame either forever, until a specified amount of time has elapsed, or until a specified condition holds true.
  2264. !
  2265. !Action methodsFor: 'accessing' stamp: 'jsp 3/9/1999 16:08'!
  2266. getAffectedObject
  2267.     "Returns the object affected by the action"
  2268.  
  2269.     ^ affectedObject.
  2270. ! !
  2271.  
  2272. !Action methodsFor: 'accessing' stamp: 'jsp 2/1/1999 15:13'!
  2273. isDone
  2274.     "Returns true if the Action is done executing either because it's lifetime has expired or because the specified condition is true"
  2275.  
  2276.     (lifetime > 0) ifTrue: [^ (lifetime < (myScheduler getTime))]
  2277.                 ifFalse: [^ (stopCondition value)].
  2278.     ! !
  2279.  
  2280. !Action methodsFor: 'accessing' stamp: 'jsp 3/9/1999 16:22'!
  2281. isPaused
  2282.     "Returns true if the action is paused"
  2283.  
  2284.     ^ paused.
  2285. ! !
  2286.  
  2287. !Action methodsFor: 'accessing' stamp: 'jsp 3/9/1999 16:21'!
  2288. pause
  2289.     "Pause the action"
  2290.  
  2291.     paused _ true.
  2292. ! !
  2293.  
  2294. !Action methodsFor: 'accessing' stamp: 'jsp 3/9/1999 16:21'!
  2295. resume
  2296.     "resume the action"
  2297.  
  2298.     paused _ false.
  2299. ! !
  2300.  
  2301. !Action methodsFor: 'management' stamp: 'jsp 3/9/1999 16:20'!
  2302. execute
  2303.     "Execute the Action's task"
  2304.  
  2305.     paused ifFalse: [ actionTask value ].
  2306.  
  2307. ! !
  2308.  
  2309. !Action methodsFor: 'management' stamp: 'jsp 3/9/1999 16:08'!
  2310. setAffectedObject: anObject
  2311.     "Sets the object affected by the action"
  2312.  
  2313.     affectedObject _ anObject.
  2314. ! !
  2315.  
  2316. !Action methodsFor: 'management' stamp: 'jsp 2/1/1999 11:44'!
  2317. setLifetime: howlong andCondition: condition
  2318.     "Sets how long the action should run, or the condition under which it should stop"
  2319.  
  2320.     lifetime _ howlong.
  2321.     stopCondition _ condition.
  2322. ! !
  2323.  
  2324. !Action methodsFor: 'management' stamp: 'jsp 2/1/1999 16:20'!
  2325. setScheduler: scheduler
  2326.     "Sets the scheduler the Action is active in"
  2327.  
  2328.     myScheduler _ scheduler.
  2329. ! !
  2330.  
  2331. !Action methodsFor: 'management' stamp: 'jsp 3/9/1999 16:20'!
  2332. setTask: task
  2333.     "Sets the task the Action should perform each frame"
  2334.  
  2335.     actionTask _ task.
  2336.     paused _ false.
  2337.  
  2338. ! !
  2339.  
  2340. !Action methodsFor: 'management' stamp: 'jsp 3/30/1999 11:50'!
  2341. stop
  2342.     "This method removes the Action from myScheduler's list of active actions"
  2343.  
  2344.     stopCondition _ [ true ].
  2345.     myScheduler removeAction: self.
  2346. ! !
  2347.  
  2348. !Action class methodsFor: 'initialize-release' stamp: 'jsp 3/9/1999 16:09'!
  2349. do: task eachframefor: time toObject: anObject inScheduler: scheduler
  2350.     "Creates a new Action that performs the specified task each frame for (time) seconds"
  2351.  
  2352.     | newAction |
  2353.     newAction _ Action new.
  2354.  
  2355.     newAction setTask: task.
  2356.     newAction setLifetime: (time + (scheduler getTime)) andCondition: [false].
  2357.     newAction setAffectedObject: anObject.
  2358.     newAction setScheduler: scheduler.
  2359.  
  2360.     scheduler addAction: newAction.
  2361.  
  2362.     ^ newAction.
  2363. ! !
  2364.  
  2365. !Action class methodsFor: 'initialize-release' stamp: 'jsp 3/9/1999 16:09'!
  2366. do: task eachframeuntil: condition toObject: anObject inScheduler: scheduler
  2367.     "Creates a new Action that performs the specified task each frame until the specified condition holds true"
  2368.  
  2369.     | newAction |
  2370.     newAction _ Action new.
  2371.  
  2372.     newAction setTask: task.
  2373.     newAction setLifetime: -1 andCondition: condition.
  2374.     newAction setAffectedObject: anObject.
  2375.     newAction setScheduler: scheduler.
  2376.  
  2377.     scheduler addAction: newAction.
  2378.  
  2379.     ^ newAction.
  2380. ! !
  2381.  
  2382. !Action class methodsFor: 'initialize-release' stamp: 'jsp 3/9/1999 16:10'!
  2383. do: task toObject: anObject inScheduler: scheduler
  2384.     "Creates a new Action that executes the specified task each frame"
  2385.  
  2386.     | newAction |
  2387.     newAction _ Action new.
  2388.  
  2389.     newAction setTask: task.
  2390.     newAction setLifetime: -1 andCondition: [false].
  2391.     newAction setAffectedObject: anObject.
  2392.     newAction setScheduler: scheduler.
  2393.  
  2394.     scheduler addAction: newAction.
  2395.  
  2396.     ^ newAction.
  2397. ! !
  2398.  
  2399. !ActiveSwikiAction methodsFor: 'as yet unclassified' stamp: 'mjg 9/1/1998
  2400. 12:44'!
  2401. browse: pageRef from: request
  2402.     "Just reply with a page in HTML format"
  2403.  
  2404.     | formattedPage liveText|
  2405.     liveText _ HTMLformatter evalEmbedded: (pageRef text)
  2406.         with: request unlessContains: (self dangerSet).
  2407.     formattedPage _ pageRef copy.
  2408.     "Make a copy, then format the text."
  2409.     formattedPage formatted: (formatter swikify: liveText
  2410.             linkhandler: [:link | urlmap
  2411.                     linkFor: link
  2412.                     from: request peerName
  2413.                     storingTo: OrderedCollection new
  2414.                     page: formattedPage]).
  2415.     request reply: ((self formatterFor: 'page') format: formattedPage).
  2416. ! !
  2417.  
  2418. !ActiveSwikiAction methodsFor: 'as yet unclassified' stamp: 'mjg 9/10/1998
  2419. 15:33'!
  2420. inputFrom: request
  2421.     "Take user's input and respond with a searchresult or store the edit"
  2422.  
  2423.     | coreRef page theText |
  2424.     coreRef _ request message size < 2
  2425.         ifTrue: ['1']
  2426.         ifFalse: [request message at: 2].
  2427.     coreRef = 'searchresult' ifTrue: [
  2428.         "If contains search string, do search"
  2429.         request reply: PWS crlf,
  2430.             (HTMLformatter evalEmbedded: (self fileContents:
  2431. source, 'results.html')
  2432.                 with: (urlmap searchFor: (request fields
  2433. at: 'searchFor' ifAbsent: ['nothing']))).
  2434.         ^ #return].
  2435.     (theText _ request fields at: 'text' ifAbsent: [nil]) ifNotNil: [
  2436.         "It's a response from an edit, so store the page"
  2437.         page _ urlmap atID: coreRef.
  2438.         page user: request peerName.  "Address is machine, user only if
  2439. logged in"
  2440.          page pageStatus = #new ifTrue: [page pageStatus: #standard].
  2441.         page _ urlmap
  2442.             storeID: coreRef
  2443.             text: theText withSqueakLineEndings
  2444.             from: request peerName.
  2445.         ^ self].    "return self means do serve the edited page
  2446. afterwards"
  2447.     request fields keys do: [:aTag |
  2448.         (aTag beginsWith: 'text-') ifTrue: [
  2449.             urlmap
  2450.                 storeID: coreRef
  2451.                 text: (request fields at: aTag)
  2452. withSqueakLineEndings
  2453.                 insertAt: (aTag copyFrom: 6 to: aTag size).
  2454.     "string"
  2455.             ^ self]].
  2456.     "oops, a new kind!! -- but don't complain!! Could be for ActivePage!!"
  2457. "    Transcript show: 'Unknown data from client. '; show: request fields
  2458. printString; cr."! !
  2459.  
  2460. !ActorState methodsFor: 'pen' stamp: 'di 9/3/1999 09:16'!
  2461. choosePenColor: evt
  2462.     evt hand changeColorTarget: owningPlayer costume selector: #penColor: originalColor: owningPlayer penColor.
  2463. ! !
  2464.  
  2465. !ActorState methodsFor: 'other' stamp: 'MPW 1/1/1901 21:53'!
  2466. printOnStream: aStream
  2467.     aStream print: 'ActorState for '; print:owningPlayer externalName; print:' '.
  2468.     penDown ifNotNil: [aStream cr; print: 'penDown '; write:penDown].
  2469.     penColor ifNotNil: [aStream cr; print: 'penColor '; write:penColor].
  2470.     penSize ifNotNil: [aStream cr; print: 'penSize '; write:penSize].
  2471.     instantiatedUserScriptsDictionary ifNotNil:
  2472.         [aStream cr; print:
  2473.             '+ '; write: instantiatedUserScriptsDictionary size; print:' user scripts'].
  2474. ! !
  2475.  
  2476. !AdvancedB3DSceneMorph methodsFor: 'accessing' stamp: 'ti 3/24/2000 16:36'!
  2477. rotationAngle
  2478.     ^rotationAngle! !
  2479.  
  2480. !AdvancedB3DSceneMorph methodsFor: 'accessing' stamp: 'ti 3/24/2000 16:36'!
  2481. rotationAngle: aNumber
  2482.     rotationAngle := aNumber! !
  2483.  
  2484. !AdvancedB3DSceneMorph methodsFor: 'accessing' stamp: 'ti 3/27/2000 16:55'!
  2485. scene: aScene
  2486.     super scene: aScene.
  2487.     self updateHeadlight.
  2488.     self changed! !
  2489.  
  2490. !AdvancedB3DSceneMorph methodsFor: 'accessing' stamp: 'ti 3/24/2000 16:35'!
  2491. stepTime
  2492.     ^stepTime! !
  2493.  
  2494. !AdvancedB3DSceneMorph methodsFor: 'accessing' stamp: 'ti 3/24/2000 16:35'!
  2495. stepTime: aNumber
  2496.     stepTime := aNumber! !
  2497.  
  2498. !AdvancedB3DSceneMorph methodsFor: 'camera actions' stamp: 'ti 3/27/2000 16:55'!
  2499. addDolly: delta
  2500.     | camera new |
  2501.     camera := scene defaultCamera.
  2502.     new := camera position - (camera direction * delta).
  2503.     camera target = new ifFalse: [
  2504.         camera position: new].
  2505.     self updateHeadlight.
  2506.     self changed.! !
  2507.  
  2508. !AdvancedB3DSceneMorph methodsFor: 'camera actions' stamp: 'ti 3/27/2000 16:55'!
  2509. addFovAngle: delta
  2510.     | camera new |
  2511.     camera := scene defaultCamera.
  2512.     new := camera fov + delta.
  2513.     0 < new ifTrue: [
  2514.         camera fov: new].
  2515.     self updateHeadlight.
  2516.     self changed.! !
  2517.  
  2518. !AdvancedB3DSceneMorph methodsFor: 'camera actions' stamp: 'ti 3/27/2000 16:54'!
  2519. panBy: aPoint
  2520.     | camera pt |
  2521.     pt := B3DVector3 x: aPoint x y: aPoint y negated z: 0.0.
  2522.      camera := scene defaultCamera.
  2523.     pt := pt * (camera direction length) / 200.
  2524.  
  2525.     pt := camera asMatrix4x4 inverseTransformation localPointToGlobal: pt.
  2526.     pt := pt - camera position.
  2527.  
  2528.     camera position: camera position + pt.
  2529.     camera target: camera target + pt.
  2530.     self updateHeadlight.
  2531.     self changed.! !
  2532.  
  2533. !AdvancedB3DSceneMorph methodsFor: 'camera actions' stamp: 'ti 3/27/2000 16:55'!
  2534. rotateX:  angle
  2535.     | camera matrix |
  2536.     camera := scene defaultCamera.
  2537.     matrix := B3DMatrix4x4
  2538.         rotatedBy: angle
  2539.         around: ((camera position - camera target) cross: camera up)
  2540.         centeredAt: camera target.
  2541.     camera position: (matrix localPointToGlobal: camera position).
  2542.     camera up: (matrix localPointToGlobal: camera up).
  2543.     self updateHeadlight.
  2544.     self changed.! !
  2545.  
  2546. !AdvancedB3DSceneMorph methodsFor: 'camera actions' stamp: 'ti 3/27/2000 16:55'!
  2547. rotateY: angle
  2548.     | camera matrix |
  2549.     camera := scene defaultCamera.
  2550.     matrix := B3DMatrix4x4
  2551.         rotatedBy: angle
  2552.         around: camera up
  2553.         centeredAt: camera target.
  2554.     camera position: (matrix localPointToGlobal: camera position).
  2555.     self updateHeadlight.
  2556.     self changed.! !
  2557.  
  2558. !AdvancedB3DSceneMorph methodsFor: 'camera actions' stamp: 'ti 3/27/2000 16:54'!
  2559. rotateZ: angle
  2560.     | camera matrix |
  2561.     camera := scene defaultCamera.
  2562.     matrix := B3DMatrix4x4
  2563.         rotatedBy: angle
  2564.         around: (camera position - camera target)
  2565.         centeredAt: camera target.
  2566.     camera up: (matrix localPointToGlobal: camera up).
  2567.     self updateHeadlight.
  2568.     self changed.! !
  2569.  
  2570. !AdvancedB3DSceneMorph methodsFor: 'camera actions' stamp: 'ti 3/27/2000 16:54'!
  2571. updateHeadlight
  2572.  
  2573.     | headLight camera |
  2574.     camera := scene defaultCamera.
  2575.     (self scene lights isKindOf: Dictionary)
  2576.         ifTrue: [headLight := self scene lights at: '$HeadLight$' ifAbsent: []]
  2577.         ifFalse: [headLight := nil].
  2578.     headLight ifNotNil: [
  2579.         headLight
  2580.             position: camera position;
  2581.             target: camera target].
  2582. ! !
  2583.  
  2584. !AdvancedB3DSceneMorph methodsFor: 'drawing' stamp: 'ti 3/24/2000 17:12'!
  2585. renderOn: aRenderer
  2586.     aRenderer getVertexBuffer flags: (aRenderer getVertexBuffer flags bitOr: VBTwoSidedLighting).
  2587.     super renderOn: aRenderer! !
  2588.  
  2589. !AdvancedB3DSceneMorph methodsFor: 'event handling' stamp: 'ti 3/24/2000 17:01'!
  2590. handlesMouseDown: evt
  2591.     evt yellowButtonPressed ifTrue: [^false] ifFalse: [^true]
  2592. ! !
  2593.  
  2594. !AdvancedB3DSceneMorph methodsFor: 'event handling' stamp: 'ti 3/24/2000 17:02'!
  2595. mouseDown: evt
  2596.     oldPoint := evt cursorPoint.
  2597.     super mouseDown: evt.! !
  2598.  
  2599. !AdvancedB3DSceneMorph methodsFor: 'event handling' stamp: 'ti 3/24/2000 17:02'!
  2600. mouseMove: evt
  2601.     oldPoint ifNil: [^super mouseMove: evt].
  2602.     ((evt redButtonPressed) and: [evt shiftPressed]) ifTrue: [
  2603.         self panBy: oldPoint - evt cursorPoint.
  2604.         oldPoint := evt cursorPoint.]! !
  2605.  
  2606. !AdvancedB3DSceneMorph methodsFor: 'initialization' stamp: 'ti 3/27/2000 10:51'!
  2607. createDefaultScene
  2608.     | camera headLight |
  2609.     super createDefaultScene.
  2610.     camera _ B3DCamera new.
  2611.     camera position: 0@0@-6.
  2612.     camera target: 0@0@0.
  2613.     camera fov: 15.0.
  2614.     scene defaultCamera: camera.
  2615.     headLight := B3DSpotLight new.
  2616.     headLight position: 0@-1@0.
  2617.     headLight target: 0@0@0.
  2618.     headLight lightColor: (B3DMaterialColor color: (Color blue)).
  2619.     headLight attenuation: (B3DLightAttenuation constant: 1.0 linear: 0.0 squared: 0.0).
  2620.     headLight minAngle: 5.
  2621.     headLight maxAngle: 6.
  2622.     scene lights add: headLight.
  2623.     scene objects do: [ :object |
  2624.         object material: nil]! !
  2625.  
  2626. !AdvancedB3DSceneMorph methodsFor: 'initialization' stamp: 'ti 3/24/2000 17:26'!
  2627. initialize
  2628.     super initialize.
  2629.     self stepTime: 0.
  2630.     self rotationAngle: 1.
  2631.     self beRotating.! !
  2632.  
  2633. !AdvancedB3DSceneMorph methodsFor: 'properties' stamp: 'ti 3/24/2000 16:37'!
  2634. beRotating
  2635.     isRotating := true.! !
  2636.  
  2637. !AdvancedB3DSceneMorph methodsFor: 'properties' stamp: 'ti 3/24/2000 16:37'!
  2638. beStill
  2639.     isRotating := false.! !
  2640.  
  2641. !AdvancedB3DSceneMorph methodsFor: 'properties' stamp: 'ti 3/24/2000 16:37'!
  2642. isRotating
  2643.     ^isRotating! !
  2644.  
  2645. !AdvancedB3DSceneMorph methodsFor: 'properties' stamp: 'ti 3/24/2000 16:37'!
  2646. switchRotationStatus
  2647.     self isRotating
  2648.         ifTrue: [self beStill]
  2649.         ifFalse: [self beRotating]! !
  2650.  
  2651. !AdvancedB3DSceneMorph methodsFor: 'stepping' stamp: 'ti 3/27/2000 16:55'!
  2652. step
  2653.     self isRotating ifTrue: [
  2654.         scene defaultCamera rotateBy: self rotationAngle.
  2655.         self updateHeadlight.
  2656.         self changed.].! !
  2657.  
  2658. This class implements the alarms for Wonderlands. The user specifies the time the alarm should go off (either in a certain amount of time or at a specific moment) and the task the system should execute when the alarm goes off.
  2659. !
  2660. !Alarm methodsFor: 'accessing' stamp: 'jsp 2/1/1999 14:50'!
  2661. checkTime
  2662.     "Returns the time the alarm is set to go off at"
  2663.  
  2664.     ^ alarmTime.
  2665. ! !
  2666.  
  2667. !Alarm methodsFor: 'management' stamp: 'jsp 1/29/1999 14:49'!
  2668. execute
  2669.     "Execute the appointed task because it's the appointed hour"
  2670.  
  2671.     alarmTask value.
  2672. ! !
  2673.  
  2674. !Alarm methodsFor: 'management' stamp: 'jsp 2/1/1999 12:12'!
  2675. setScheduler: scheduler
  2676.     "Set the Scheduler that manages this Alarm"
  2677.  
  2678.     myScheduler _ scheduler.
  2679. ! !
  2680.  
  2681. !Alarm methodsFor: 'management' stamp: 'jsp 2/1/1999 10:58'!
  2682. setTask: task
  2683.     "Specifies the task the alarm executes when it goes off"
  2684.  
  2685.     alarmTask _ task.
  2686. ! !
  2687.  
  2688. !Alarm methodsFor: 'management' stamp: 'jsp 2/1/1999 10:59'!
  2689. setTime: time
  2690.     "Specifies the time the alarm goes off"
  2691.  
  2692.     alarmTime _ time.
  2693. ! !
  2694.  
  2695. !Alarm methodsFor: 'management' stamp: 'jsp 2/1/1999 16:33'!
  2696. stop
  2697.     "This method removes the Alarm from myScheduler's list of active Alarms"
  2698.  
  2699.     myScheduler removeAlarm: self.
  2700. ! !
  2701.  
  2702. !Alarm class methodsFor: 'intialize-release' stamp: 'jsp 2/8/1999 16:07'!
  2703. do: task at: executeTime inScheduler: scheduler
  2704.     "Creates an alarm that does the specified task at the specified time"
  2705.  
  2706.     | newAlarm |
  2707.     newAlarm _ Alarm new.
  2708.  
  2709.     newAlarm setTime: executeTime.
  2710.     newAlarm setTask: task.
  2711.     newAlarm setScheduler: scheduler.
  2712.  
  2713.     scheduler addAlarm: newAlarm.
  2714.  
  2715.     ^ newAlarm.! !
  2716.  
  2717. !Alarm class methodsFor: 'intialize-release' stamp: 'jsp 2/8/1999 16:06'!
  2718. do: task in: waitTime inScheduler: scheduler
  2719.     "This sets an alarm that will expire in waitTime seconds and execute the specified task"
  2720.  
  2721.     | newAlarm |
  2722.     newAlarm _ Alarm new.
  2723.  
  2724.     newAlarm setTask: task.
  2725.     newAlarm setTime: waitTime + (scheduler getTime).
  2726.     newAlarm setScheduler: scheduler.
  2727.  
  2728.     scheduler addAlarm: newAlarm.
  2729.  
  2730.     ^ newAlarm.
  2731. ! !
  2732.  
  2733. !AliceAbsoluteAnimation methodsFor: 'initialization' stamp: 'jsp 7/20/1999 00:12'!
  2734. prologue: currentTime
  2735.     "Extends the AliceAbstractAnimation prologue by saving the start state of the animation."
  2736.  
  2737.     undoable ifTrue: [
  2738.                         (myWonderland getUndoStack)
  2739.                                 push: (AliceUndoAnimation new: (self makeUndoVersion)).
  2740.                     ].
  2741.  
  2742.     (direction = Forward) ifTrue: [
  2743.                                     startState _ getStartStateFunction value.
  2744.                                     lastStartState _ startState.
  2745.                                     endState _ getEndStateFunction value.
  2746.                                 ]
  2747.                         ifFalse: [
  2748.                                     startState _ getStartStateFunction value.
  2749.                                     endState _ lastStartState.
  2750.                                 ].
  2751.  
  2752.  
  2753.     super prologue: currentTime.
  2754. ! !
  2755.  
  2756. !AliceAbsoluteAnimation methodsFor: 'management' stamp: 'jsp 7/20/1999 00:12'!
  2757. object: anObject update: func getStartState: startFunc getEndState: endFunc style: styleFunc duration: time undoable: canUndo inWonderland: aWonderland
  2758.     "This method initializes the animation with all the information that it needs to run."
  2759.  
  2760.     lastStartState _ startFunc value.
  2761.  
  2762.     super object: anObject update: func getStartState: startFunc getEndState: endFunc style: styleFunc duration: time undoable: canUndo inWonderland: aWonderland.
  2763. ! !
  2764.  
  2765. !AliceAbsoluteAnimation methodsFor: 'copying' stamp: 'jsp 7/20/1999 00:02'!
  2766. copy
  2767.     "Creates a copy of the animation"
  2768.  
  2769.     | anim |
  2770.  
  2771.     anim _ AliceAbsoluteAnimation new.
  2772.  
  2773.     anim object: animatedObject
  2774.         update: updateFunction
  2775.         getStartState: getStartStateFunction
  2776.         getEndState: getEndStateFunction
  2777.         style: styleFunction
  2778.         duration: duration
  2779.         undoable: undoable
  2780.         inWonderland: myWonderland.
  2781.  
  2782.     (direction = Forward) ifFalse: [ anim reverseDirection ].
  2783.  
  2784.     ^ anim.
  2785. ! !
  2786.  
  2787. !AliceAbsoluteAnimation methodsFor: 'copying' stamp: 'jsp 7/20/1999 00:03'!
  2788. makeUndoVersion
  2789.     "Creates the undo version of an animation"
  2790.  
  2791.     | anim |
  2792.  
  2793.     anim _ AliceAbsoluteAnimation new.
  2794.  
  2795.     anim object: animatedObject
  2796.         update: updateFunction
  2797.         getStartState: getStartStateFunction
  2798.         getEndState: getEndStateFunction
  2799.         style: styleFunction
  2800.         duration: 0.5
  2801.         undoable: false
  2802.         inWonderland: myWonderland.
  2803.  
  2804.     anim stop.
  2805.     (direction = Forward) ifTrue: [ anim reverseDirection ].
  2806.  
  2807.     ^ anim.
  2808. ! !
  2809.  
  2810. !AliceAbsoluteAnimation methodsFor: 'copying' stamp: 'jsp 7/20/1999 00:07'!
  2811. reversed
  2812.     "Creates a reversed version of an animation"
  2813.  
  2814.     | anim |
  2815.  
  2816.     anim _ self copy reverseDirection.
  2817.  
  2818.     ^ anim.
  2819. ! !
  2820.  
  2821. !AliceAbstractAnimation methodsFor: 'accessing' stamp: 'jsp 7/19/1999 23:02'!
  2822. getAnimatedObject
  2823.     "Return the object that this animation affects"
  2824.  
  2825.     ^ animatedObject.
  2826. ! !
  2827.  
  2828. !AliceAbstractAnimation methodsFor: 'accessing' stamp: 'jsp 7/19/1999 23:02'!
  2829. getLoopCount
  2830.     "Returns the animation's current loop count"
  2831.  
  2832.     ^ loopCount.
  2833. ! !
  2834.  
  2835. !AliceAbstractAnimation methodsFor: 'accessing' stamp: 'jsp 7/19/1999 23:02'!
  2836. getState
  2837.     "Returns the current state of the animation."
  2838.  
  2839.     ^ state.
  2840. ! !
  2841.  
  2842. !AliceAbstractAnimation methodsFor: 'accessing' stamp: 'jsp 7/19/1999 23:03'!
  2843. isDone
  2844.     "Returns true if the animation is running"
  2845.  
  2846.     ^ (state = Stopped).
  2847. ! !
  2848.  
  2849. !AliceAbstractAnimation methodsFor: 'accessing' stamp: 'jsp 7/19/1999 23:03'!
  2850. isLooping
  2851.     "Returns true if the animation is looping"
  2852.  
  2853.     ^ ( loopCount > 1) or: [ loopCount = Infinity ].
  2854. ! !
  2855.  
  2856. !AliceAbstractAnimation methodsFor: 'accessing' stamp: 'jsp 7/19/1999 23:03'!
  2857. setLoopCount: count
  2858.     "Sets the animation's current loop count"
  2859.  
  2860.     loopCount _ count.
  2861.  
  2862. ! !
  2863.  
  2864. !AliceAbstractAnimation methodsFor: 'accessing' stamp: 'jsp 7/19/1999 23:03'!
  2865. setUndoable: aBoolean
  2866.     "Sets the animation's undoable property"
  2867.  
  2868.     undoable _ aBoolean.
  2869. ! !
  2870.  
  2871. !AliceAbstractAnimation methodsFor: 'management' stamp: 'jsp 7/19/1999 23:04'!
  2872. copy
  2873.  
  2874.     self subclassResponsibility.
  2875. ! !
  2876.  
  2877. !AliceAbstractAnimation methodsFor: 'management' stamp: 'jsp 7/19/1999 23:04'!
  2878. epilogue: currentTime
  2879.     "This method does any work that needs to be done after an interation of the animation finishes."
  2880.  
  2881.     (loopCount = Infinity) ifTrue:
  2882.                 [state _ Waiting]
  2883.     ifFalse:
  2884.                 [
  2885.                     loopCount _ loopCount - 1.
  2886.  
  2887.                     (loopCount > 0) ifTrue: [ state _ Waiting ]
  2888.                                     ifFalse: [state _ Stopped.
  2889.                                              loopCount _ 1 ].
  2890.                 ].
  2891.  
  2892. ! !
  2893.  
  2894. !AliceAbstractAnimation methodsFor: 'management' stamp: 'jsp 7/19/1999 23:04'!
  2895. getDuration
  2896.     "This method returns the duration of the animation."
  2897.  
  2898.     ^ duration.
  2899. ! !
  2900.  
  2901. !AliceAbstractAnimation methodsFor: 'management' stamp: 'jsp 7/19/1999 23:04'!
  2902. loop
  2903.     "This method causes an animation to loop forever."
  2904.  
  2905.     loopCount _ Infinity.
  2906.  
  2907.     (state = Stopped) ifTrue: [ state _ Waiting.
  2908.                               myScheduler addAnimation: self. ].
  2909. ! !
  2910.  
  2911. !AliceAbstractAnimation methodsFor: 'management' stamp: 'jsp 7/19/1999 23:05'!
  2912. loop: numberOfTimes
  2913.     "This method causes an animation to loop for the specified number of times."
  2914.  
  2915.     loopCount _ numberOfTimes.
  2916.  
  2917.     (state = Stopped) ifTrue: [ state _ Waiting.
  2918.                               myScheduler addAnimation: self. ].
  2919. ! !
  2920.  
  2921. !AliceAbstractAnimation methodsFor: 'management' stamp: 'jsp 7/19/1999 23:05'!
  2922. looped
  2923.     "This method creates a copy of an animation and loops it forever."
  2924.  
  2925.     | anim |
  2926.  
  2927.     anim _ self copy.
  2928.     anim setLoopCount: Infinity.
  2929.  
  2930.     ^ anim.
  2931. ! !
  2932.  
  2933. !AliceAbstractAnimation methodsFor: 'management' stamp: 'jsp 7/19/1999 23:05'!
  2934. looped: numberOfTimes
  2935.     "This method creates a copy of an animation and loops it for the specified number of times."
  2936.  
  2937.     | anim |
  2938.  
  2939.     anim _ self copy.
  2940.     anim setLoopCount: numberOfTimes.
  2941.  
  2942.     ^ anim.
  2943. ! !
  2944.  
  2945. !AliceAbstractAnimation methodsFor: 'management' stamp: 'jsp 7/19/1999 23:05'!
  2946. pause
  2947.     "This method pauses an active Animation."
  2948.  
  2949.     (state = Running) ifTrue: [ state _ Paused. 
  2950.                                 pausedInterval _ (myScheduler getTime) - startTime.].
  2951. ! !
  2952.  
  2953. !AliceAbstractAnimation methodsFor: 'management' stamp: 'jsp 7/19/1999 23:07'!
  2954. prologue: currentTime
  2955.     "This method does any work that needs to be done before the animation starts, including possibly adding the current state to the undo stack."
  2956.  
  2957.     startTime _ currentTime.
  2958.     endTime _ startTime + duration.
  2959.     state _ Running.
  2960. ! !
  2961.  
  2962. !AliceAbstractAnimation methodsFor: 'management' stamp: 'jsp 7/20/1999 01:04'!
  2963. resume
  2964.     "This method resumes a paused animation"
  2965.  
  2966.     (state = Paused) ifTrue:
  2967.         [
  2968.             state _ Running.
  2969.             startTime _ (myScheduler getTime) - pausedInterval.
  2970.             endTime _ startTime + duration.
  2971.         ]
  2972.     ifFalse: [(state = Stopped) ifTrue:
  2973.                 [
  2974.                     state _ Waiting.
  2975.                     myScheduler addUpdateItem: self.
  2976.                 ].
  2977.             ]
  2978.  
  2979.  
  2980. ! !
  2981.  
  2982. !AliceAbstractAnimation methodsFor: 'management' stamp: 'jsp 7/20/1999 01:10'!
  2983. start
  2984.     "This method starts an existing animation"
  2985.  
  2986.     state _ Waiting.
  2987.     loopCount _ 1.
  2988.     myScheduler addUpdateItem: self.
  2989. ! !
  2990.  
  2991. !AliceAbstractAnimation methodsFor: 'management' stamp: 'jsp 7/20/1999 01:10'!
  2992. stop
  2993.     "This method changes the state of an animation to stopped.  If it is currently active, the Scheduler will remove it from the list of active animations."
  2994.  
  2995.     state _ Stopped.
  2996. ! !
  2997.  
  2998. !AliceAbstractAnimation methodsFor: 'management' stamp: 'jsp 7/20/1999 01:10'!
  2999. stopLooping
  3000.     "This method causes the animation to stop looping; the current interation of the animation completes before the animation stops."
  3001.  
  3002.     loopCount _ 1.
  3003. ! !
  3004.  
  3005. !AliceAbstractAnimation methodsFor: 'management' stamp: 'jsp 7/28/1999 21:51'!
  3006. update: currentTime
  3007.     "Updates the animation using the current Wonderland time"
  3008.  
  3009.     | newState |
  3010.  
  3011.     (state = Waiting) ifTrue: [self prologue: currentTime].
  3012.  
  3013.     (state = Running) ifTrue: [
  3014.                 proportionDone _ styleFunction value: (currentTime - startTime) value: duration.
  3015.                 newState _ startState interpolateTo: endState at: proportionDone.
  3016.                 updateFunction value: newState.
  3017.                 (currentTime >= endTime) ifTrue: [ state _ Finished. ].
  3018.                               ].
  3019.  
  3020.     (state = Finished) ifTrue: [self epilogue: currentTime].! !
  3021.  
  3022. !AliceAbstractAnimation methodsFor: 'reversing' stamp: 'jsp 7/19/1999 23:01'!
  3023. reverseDirection
  3024.     "Changes the direction an animation runs in (forward or in reverse)"
  3025.  
  3026.     (direction = Forward) ifTrue: [ direction _ Reverse ]
  3027.                          ifFalse: [ direction _ Forward ].
  3028. ! !
  3029.  
  3030. !AliceAbstractAnimation methodsFor: 'private' stamp: 'jsp 7/19/1999 23:00'!
  3031. scaleDuration: scaleAmount
  3032.     "Scales the animation's duration by the specified amount"
  3033.  
  3034.     duration _ duration * scaleAmount.
  3035. ! !
  3036.  
  3037. !AliceAbstractAnimation methodsFor: 'private' stamp: 'jsp 7/19/1999 23:01'!
  3038. setDirection: aDirection
  3039.     "Sets the animation's direction variable"
  3040.  
  3041.     direction _ aDirection.
  3042. ! !
  3043.  
  3044. !AliceAbstractAnimation methodsFor: 'initialization' stamp: 'jsp 7/28/1999 21:51'!
  3045. object: anObject update: func getStartState: startFunc getEndState: endFunc style: styleFunc duration: time undoable: canUndo inWonderland: aWonderland
  3046.     "This method initializes the Animation with all the information that it needs run."
  3047.  
  3048.     animatedObject _ anObject.
  3049.     updateFunction _ func.
  3050.     styleFunction _ styleFunc.
  3051.     getStartStateFunction _ startFunc.
  3052.     getEndStateFunction _ endFunc.
  3053.     duration _ time.
  3054.     undoable _ canUndo.
  3055.     myScheduler _ aWonderland getScheduler.
  3056.     myWonderland _ aWonderland.
  3057.     loopCount _ 1.
  3058.     direction _ Forward.
  3059.  
  3060.     state _ Waiting.
  3061.     myScheduler addAnimation: self.! !
  3062.  
  3063. !AliceAbstractAnimation class methodsFor: 'class initialization' stamp: 'jsp 7/19/1999 22:57'!
  3064. initialize
  3065.     "Initialize the class variables"
  3066.  
  3067.     Waiting _ 1.
  3068.     Running _ 2.
  3069.     Paused _ 3.
  3070.     Finished _ 4.
  3071.     Stopped _ 5.
  3072.  
  3073.     Forward _ 0.
  3074.     Reverse _ 1.
  3075.  
  3076.     Infinity _ -1.
  3077. ! !
  3078.  
  3079. !AliceAction methodsFor: 'accessing' stamp: 'jsp 7/19/1999 22:06'!
  3080. getAffectedObject
  3081.     "Returns the object affected by the action"
  3082.  
  3083.     ^ affectedObject.
  3084. ! !
  3085.  
  3086. !AliceAction methodsFor: 'accessing' stamp: 'jsp 7/19/1999 22:08'!
  3087. isDone
  3088.     "Returns true if the action is done executing either because it's lifetime has expired or because the specified condition is true"
  3089.  
  3090.     (lifetime > 0) ifTrue: [^ (lifetime < (myScheduler getTime))]
  3091.                 ifFalse: [^ (stopCondition value)].
  3092.     ! !
  3093.  
  3094. !AliceAction methodsFor: 'accessing' stamp: 'jsp 7/19/1999 22:27'!
  3095. isPaused
  3096.     "Returns true if the action is paused"
  3097.  
  3098.     ^ paused.
  3099. ! !
  3100.  
  3101. !AliceAction methodsFor: 'accessing' stamp: 'jsp 7/19/1999 22:28'!
  3102. pause
  3103.     "Pause the action"
  3104.  
  3105.     paused _ true.
  3106. ! !
  3107.  
  3108. !AliceAction methodsFor: 'accessing' stamp: 'jsp 7/19/1999 22:28'!
  3109. resume
  3110.     "resume the action"
  3111.  
  3112.     paused _ false.
  3113. ! !
  3114.  
  3115. !AliceAction methodsFor: 'management' stamp: 'jsp 7/19/1999 22:29'!
  3116. setAffectedObject: anObject
  3117.     "Sets the object affected by the action"
  3118.  
  3119.     affectedObject _ anObject.
  3120. ! !
  3121.  
  3122. !AliceAction methodsFor: 'management' stamp: 'jsp 7/19/1999 22:29'!
  3123. setLifetime: howlong andCondition: condition
  3124.     "Sets how long the action should run, or the condition under which it should stop"
  3125.  
  3126.     lifetime _ howlong.
  3127.     stopCondition _ condition.
  3128. ! !
  3129.  
  3130. !AliceAction methodsFor: 'management' stamp: 'jsp 7/19/1999 22:29'!
  3131. setTask: task
  3132.     "Sets the task the Action should perform each frame"
  3133.  
  3134.     actionTask _ task.
  3135.     paused _ false.
  3136.  
  3137. ! !
  3138.  
  3139. !AliceAction methodsFor: 'management' stamp: 'jsp 7/19/1999 22:29'!
  3140. stop
  3141.     "This method removes the Action from myScheduler's list of active actions"
  3142.  
  3143.     stopCondition _ [ true ].
  3144.     myScheduler removeAction: self.
  3145. ! !
  3146.  
  3147. !AliceAction methodsFor: 'update' stamp: 'jsp 7/19/1999 22:30'!
  3148. update: currentTime
  3149.     "Execute the Action's task"
  3150.  
  3151.     paused ifFalse: [ actionTask value ].
  3152.  
  3153. ! !
  3154.  
  3155. !AliceAction class methodsFor: 'initialize-release' stamp: 'jsp 7/19/1999 22:31'!
  3156. do: task eachframefor: time toObject: anObject inScheduler: scheduler
  3157.     "Creates a new AliceAction that performs the specified task each frame for (time) seconds"
  3158.  
  3159.     | newAction |
  3160.     newAction _ AliceAction new.
  3161.  
  3162.     newAction setTask: task.
  3163.     newAction setLifetime: (time + (scheduler getTime)) andCondition: [false].
  3164.     newAction setAffectedObject: anObject.
  3165.     newAction setScheduler: scheduler.
  3166.  
  3167.     scheduler addUpdateItem: newAction.
  3168.  
  3169.     ^ newAction.
  3170. ! !
  3171.  
  3172. !AliceAction class methodsFor: 'initialize-release' stamp: 'jsp 7/19/1999 22:32'!
  3173. do: task eachframeuntil: condition toObject: anObject inScheduler: scheduler
  3174.     "Creates a new AliceAction that performs the specified task each frame until the specified condition holds true"
  3175.  
  3176.     | newAction |
  3177.     newAction _ AliceAction new.
  3178.  
  3179.     newAction setTask: task.
  3180.     newAction setLifetime: -1 andCondition: condition.
  3181.     newAction setAffectedObject: anObject.
  3182.     newAction setScheduler: scheduler.
  3183.  
  3184.     scheduler addUpdateItem: newAction.
  3185.  
  3186.     ^ newAction.
  3187. ! !
  3188.  
  3189. !AliceAction class methodsFor: 'initialize-release' stamp: 'jsp 7/19/1999 22:33'!
  3190. do: task toObject: anObject inScheduler: scheduler
  3191.     "Creates a new AliceAction that executes the specified task each frame"
  3192.  
  3193.     | newAction |
  3194.     newAction _ AliceAction new.
  3195.  
  3196.     newAction setTask: task.
  3197.     newAction setLifetime: -1 andCondition: [false].
  3198.     newAction setAffectedObject: anObject.
  3199.     newAction setScheduler: scheduler.
  3200.  
  3201.     scheduler addUpdateItem: newAction.
  3202.  
  3203.     ^ newAction.
  3204. ! !
  3205.  
  3206. !AliceActor methodsFor: 'initialization' stamp: 'jsp 6/9/1999 00:11'!
  3207. initializeFor: anAliceWorld
  3208.     "Initialize the instance variables for the AliceActor"
  3209.  
  3210.     super initialize.
  3211.  
  3212.     myName _ 'Unnamed'.
  3213.     myWorld _ myWorld.
  3214.     myParent _ myWorld getScene.
  3215.     myParent addChild: self.
  3216.  
  3217.     "Initialize our material"
  3218.     myMaterial _ B3DMaterial new.
  3219.     myMaterial ambientPart: Color white.
  3220.     myMaterial diffusePart: Color white.
  3221.     myMaterial specularPart: Color white.
  3222.  
  3223.     "Set up our default properties"
  3224.     myColor _ B3DColor4 r: 1.0 g: 1.0 b: 1.0 a: 1.0.
  3225.     compositeMatrix _ B3DMatrix4x4 identity.
  3226.     scaleMatrix _ B3DMatrix4x4 identity.
  3227.  
  3228.     isHidden _ false.
  3229.     isFirstClass _ true.
  3230. ! !
  3231.  
  3232. !AliceActor methodsFor: 'drawing' stamp: 'jsp 6/9/1999 00:16'!
  3233. drawMesh: aRenderer
  3234.     "Draw the mesh for this actor."
  3235.  
  3236.     myMaterial ifNotNil: [
  3237.             aRenderer pushMaterial.
  3238.             aRenderer material: myMaterial.
  3239.                         ].
  3240.  
  3241.     myTexture ifNotNil: [
  3242.             aRenderer pushTexture.
  3243.             aRenderer texture: myTexture.
  3244.                         ].
  3245.  
  3246.     "Note from Andreas: Using myMesh>>renderOn: here prevents meshes
  3247.         from being picked!!"
  3248.     myMesh ifNotNil: [ myMesh renderOn: aRenderer ].
  3249.  
  3250.     myTexture ifNotNil: [ aRenderer popTexture ].
  3251.  
  3252.     myMaterial ifNotNil: [ aRenderer popMaterial ].
  3253. ! !
  3254.  
  3255. !AliceActor methodsFor: 'drawing' stamp: 'jsp 6/9/1999 00:14'!
  3256. renderOn: aRenderer
  3257.     "Draw the actor."
  3258.  
  3259.     "Save the old transformation matrix"
  3260.     aRenderer pushMatrix.
  3261.  
  3262.     "Modify the matrix using our composite matrix for position and orientation"
  3263.     aRenderer transformBy: compositeMatrix.
  3264.  
  3265.     "Save the new transformation matrix"
  3266.     aRenderer pushMatrix.
  3267.  
  3268.     "Modify the matrix using our scale matrix - we do this seperately to avoid scaling space"
  3269.     aRenderer transformBy: scaleMatrix.
  3270.  
  3271.     "Draw our mesh if the object is not hidden"
  3272.     (isHidden) ifFalse: [ self drawMesh: aRenderer ].
  3273.  
  3274.     "Remove the scaling matrix"
  3275.     aRenderer popMatrix.
  3276.  
  3277.     "Draw our children.
  3278.     Note: For correct picking it is important to use B3DRenderEngine>>render: here."
  3279.     myChildren do: [:child | aRenderer render: child].
  3280.  
  3281.     "Restore the old transformation matrix"
  3282.     aRenderer popMatrix.! !
  3283.  
  3284. !AliceActor class methodsFor: 'instance creation' stamp: 'jsp 6/9/1999 00:10'!
  3285. newFor: anAliceWorld
  3286.     "Create a new instance for this World."
  3287.  
  3288.     ^ super new initializeFor: anAliceWorld.
  3289. ! !
  3290.  
  3291. !AliceActor class methodsFor: 'unique name creation' stamp: 'jsp 6/9/1999 00:09'!
  3292. uniqueNameFrom: aName
  3293.     "If aName is not an instance variable of this class, returns aName.  Otherwise it returns a unique name based on aName that is not an instance var."
  3294.  
  3295.     | index |
  3296.  
  3297.     (self instVarNames includes: aName) ifFalse: [ ^ aName ].
  3298.  
  3299.     index _ 2.
  3300.     [ self instVarNames includes: (aName , (index asString)) ]
  3301.         whileTrue: [ index _ index + 1 ].
  3302.  
  3303.     ^ aName , (index asString).
  3304.     ! !
  3305.  
  3306. !AliceAlarm methodsFor: 'accessing' stamp: 'jsp 7/19/1999 21:17'!
  3307. checkTime
  3308.     "Returns the time the alarm is set to go off at"
  3309.  
  3310.     ^ alarmTime.
  3311. ! !
  3312.  
  3313. !AliceAlarm methodsFor: 'accessing' stamp: 'jsp 7/20/1999 01:06'!
  3314. isDone
  3315.     "Returns true if the alarm has expired."
  3316.  
  3317.     ^ (myScheduler getTime) > alarmTime.
  3318. ! !
  3319.  
  3320. !AliceAlarm methodsFor: 'management' stamp: 'jsp 7/20/1999 01:06'!
  3321. setTask: task
  3322.     "Specifies the task the alarm executes when it goes off.  Also sets isDone to false because the task has not yet been executed."
  3323.  
  3324.     alarmTask _ task.
  3325.  
  3326. ! !
  3327.  
  3328. !AliceAlarm methodsFor: 'management' stamp: 'jsp 7/19/1999 21:21'!
  3329. setTime: time
  3330.     "Specifies the time the alarm goes off"
  3331.  
  3332.     alarmTime _ time.
  3333. ! !
  3334.  
  3335. !AliceAlarm methodsFor: 'management' stamp: 'jsp 7/20/1999 01:06'!
  3336. stop
  3337.     "This method stops the alarm."
  3338.  
  3339.     myScheduler removeUpdateItem: self.
  3340. ! !
  3341.  
  3342. !AliceAlarm methodsFor: 'update' stamp: 'jsp 7/20/1999 01:06'!
  3343. update: currentTime
  3344.     "If the alarm's time has expired, then execute the task associated with the alarm."
  3345.  
  3346.     (alarmTime < currentTime)
  3347.             ifTrue:    [ self execute ].
  3348.  
  3349.  
  3350. ! !
  3351.  
  3352. !AliceAlarm class methodsFor: 'instance creation' stamp: 'jsp 7/19/1999 22:00'!
  3353. do: task at: executeTime inScheduler: scheduler
  3354.     "Creates an alarm that does the specified task at the specified time"
  3355.  
  3356.     | newAlarm |
  3357.     newAlarm _ AliceAlarm new.
  3358.  
  3359.     newAlarm setTime: executeTime.
  3360.     newAlarm setTask: task.
  3361.     newAlarm setScheduler: scheduler.
  3362.  
  3363.     scheduler addUpdateItem: newAlarm.
  3364.  
  3365.     ^ newAlarm.! !
  3366.  
  3367. !AliceAlarm class methodsFor: 'instance creation' stamp: 'jsp 7/19/1999 22:01'!
  3368. do: task in: waitTime inScheduler: scheduler
  3369.     "This sets an alarm that will expire in waitTime seconds and execute the specified task"
  3370.  
  3371.     | newAlarm |
  3372.     newAlarm _ AliceAlarm new.
  3373.  
  3374.     newAlarm setTask: task.
  3375.     newAlarm setTime: waitTime + (scheduler getTime).
  3376.     newAlarm setScheduler: scheduler.
  3377.  
  3378.     scheduler addAlarm: newAlarm.
  3379.  
  3380.     ^ newAlarm.
  3381. ! !
  3382.  
  3383. !AliceHierarchical methodsFor: 'initialization' stamp: 'jsp 6/8/1999 23:52'!
  3384. initialize
  3385.     "Initialize this instance"
  3386.  
  3387.     myChildren _ OrderedCollection new.
  3388. ! !
  3389.  
  3390. !AliceHierarchical methodsFor: 'parent-child' stamp: 'jsp 6/8/1999 23:57'!
  3391. getAllChildren
  3392.     "Return all of this instance's children"
  3393.  
  3394.     | children |
  3395.  
  3396.     children _ OrderedCollection new.
  3397.  
  3398.     myChildren do: [:child | children addLast: child.
  3399.                         children _ children , (child getAllChildren).
  3400.                     ].
  3401.  
  3402.     ^ children.! !
  3403.  
  3404. !AliceHierarchical methodsFor: 'parent-child' stamp: 'jsp 6/8/1999 23:58'!
  3405. getChildren
  3406.     "Return the object's immediate children."
  3407.  
  3408.     ^ (myChildren copy).
  3409. ! !
  3410.  
  3411. !AliceHierarchical methodsFor: 'parent-child' stamp: 'jsp 6/8/1999 23:59'!
  3412. getParent
  3413.     "Return the object's parent."
  3414.  
  3415.     ^ myParent.
  3416. ! !
  3417.  
  3418. !AliceHierarchical methodsFor: 'parent-child' stamp: 'jsp 6/8/1999 23:59'!
  3419. setParent: anObject
  3420.     "Set this instance's parent"
  3421.  
  3422.     myParent _ anObject.
  3423. ! !
  3424.  
  3425. !AliceHierarchical methodsFor: 'private' stamp: 'jsp 6/8/1999 23:54'!
  3426. addChild: aChild
  3427.     "Add an object to this instance's list of children. Checks to make sure that aChild is not already a child of this object"
  3428.  
  3429.     ((myChildren identityIndexOf: aChild) = 0) ifTrue: [ myChildren addLast: aChild ].
  3430. ! !
  3431.  
  3432. !AliceHierarchical methodsFor: 'private' stamp: 'jsp 6/8/1999 23:59'!
  3433. appendChildrenNamesTo: prefix
  3434.     "Return the object's children's names, each appended to the prefix."
  3435.  
  3436.     | nameList |
  3437.  
  3438.     nameList _ OrderedCollection new.
  3439.     myChildren do: [:child | nameList addLast: (prefix , (child getName)).
  3440.                             nameList _ nameList , (child appendChildrenNamesTo: (prefix , '    '))].
  3441.  
  3442.     ^ nameList.
  3443. ! !
  3444.  
  3445. !AliceHierarchical methodsFor: 'private' stamp: 'jsp 6/8/1999 23:58'!
  3446. getChildrenNames
  3447.     "Return the object's children."
  3448.  
  3449.     ^ myChildren collect: [: child | child asString ].
  3450. ! !
  3451.  
  3452. !AliceHierarchical methodsFor: 'private' stamp: 'jsp 6/8/1999 23:57'!
  3453. removeChild: aChild
  3454.     "Remove an object from this instance's list of children"
  3455.  
  3456.     myChildren remove: aChild ifAbsent: [].
  3457.  
  3458. ! !
  3459.  
  3460. !AliceHierarchical class methodsFor: 'instance creation' stamp: 'jsp 6/8/1999 23:52'!
  3461. new
  3462.     "Create and initialize a new instance."
  3463.  
  3464.     ^ super new initialize.
  3465. ! !
  3466.  
  3467. !AliceNamespace methodsFor: 'initialize' stamp: 'jsp 6/7/1999 21:49'!
  3468. initialize
  3469.     "Initialize the namespace"
  3470.  
  3471.     myDictionary _ AliceConstants copy.
  3472.  
  3473.     myWorkspace _ Workspace new.
  3474.     myWorkspace setBindings: myDictionary.
  3475.     myWorkspace embeddedInMorphicWindowLabeled: 'Namespace'.
  3476. ! !
  3477.  
  3478. !AliceNamespace methodsFor: 'accessing' stamp: 'jsp 6/7/1999 21:43'!
  3479. at: key
  3480.     "Return the value in the namespace associated with the key"
  3481.  
  3482.     ^ myDictionary at: key.
  3483. ! !
  3484.  
  3485. !AliceNamespace methodsFor: 'accessing' stamp: 'jsp 6/7/1999 21:43'!
  3486. at: key put: value
  3487.     "Store the value in the namespace under the key"
  3488.  
  3489.     myDictionary at: key put: value.
  3490. ! !
  3491.  
  3492. !AliceNamespace methodsFor: 'accessing' stamp: 'jsp 6/7/1999 21:42'!
  3493. getDictionary
  3494.     "Return the namespace dictionary"
  3495.  
  3496.     ^ myDictionary.
  3497. ! !
  3498.  
  3499. !AliceNamespace methodsFor: 'accessing' stamp: 'jsp 6/7/1999 21:44'!
  3500. getEvaluationContext
  3501.     "Return a context containing the namespace for evaluating a statement "
  3502.  
  3503.     ^ (myWorkspace dependents last select model: myWorkspace).
  3504. ! !
  3505.  
  3506. !AliceNamespace methodsFor: 'accessing' stamp: 'jsp 6/8/1999 21:55'!
  3507. includesKey: aKey
  3508.     "Return true if the namespace includes the key"
  3509.  
  3510.     ^ myDictionary includesKey: aKey.
  3511. ! !
  3512.  
  3513. !AliceNamespace methodsFor: 'accessing' stamp: 'jsp 6/8/1999 22:57'!
  3514. removeKey: theKey
  3515.     "Remove the key from the namespace"
  3516.  
  3517.     myDictionary removeKey: theKey ifAbsent: [].
  3518. ! !
  3519.  
  3520. !AliceNamespace methodsFor: 'accessing' stamp: 'jsp 6/8/1999 22:57'!
  3521. removeKey: theKey ifAbsent: failBlock
  3522.     "Remove the key from the namespace. If the key isn't there, run the code in the fail block."
  3523.  
  3524.     myDictionary removeKey: theKey ifAbsent: failBlock.
  3525. ! !
  3526.  
  3527. !AliceNamespace class methodsFor: 'instance creation' stamp: 'jsp 6/7/1999 21:46'!
  3528. new
  3529.     "Create a new namespace for an Alice world"
  3530.  
  3531.     ^ super new initialize.
  3532. ! !
  3533.  
  3534. !AlicePoolDefiner class methodsFor: 'class initialization' stamp: 'jsp 6/7/1999 14:58'!
  3535. initialize
  3536.     "Initialize the Alice 2.0 pool dictionary"
  3537.  
  3538.     self initPool.
  3539. ! !
  3540.  
  3541. !AlicePoolDefiner class methodsFor: 'pool definition' stamp: 'jsp 6/29/1999 00:06'!
  3542. initPool
  3543.     "Create the pool dictionary if necessary"
  3544.  
  3545.     | poolName |
  3546.     poolName _ #AliceConstants.
  3547.     (Smalltalk includesKey: poolName) ifFalse:[
  3548.         Smalltalk declare: poolName from: Undeclared.
  3549.     ].
  3550.  
  3551.     (Smalltalk at: poolName) isNil ifTrue:[
  3552.         (Smalltalk associationAt: poolName)
  3553.                 value: ((Smalltalk at: #WonderlandConstants) copy).
  3554.     ].
  3555.  
  3556.     self initPool: (Smalltalk at: poolName).! !
  3557.  
  3558. !AlicePoolDefiner class methodsFor: 'pool definition' stamp: 'jsp 6/7/1999 15:03'!
  3559. initPool: aDictionary
  3560.     "Initialize the dictionary"
  3561.  
  3562.     aDictionary at: #inOrder put: #inOrder.
  3563.     aDictionary at: #together put: #together.
  3564. ! !
  3565.  
  3566. !AliceRelativeAnimation methodsFor: 'initialization' stamp: 'jsp 7/20/1999 00:15'!
  3567. object: anObject update: func getStartState: startFunc getEndState: endFunc getReverseState: reverseFunc style: styleFunc duration: time undoable: canUndo inWonderland: aWonderland
  3568.     "This method initializes the Animation with all the information that it needs to run."
  3569.  
  3570.     getReverseStateFunction _ reverseFunc.
  3571.  
  3572.     super object: anObject update: func getStartState: startFunc getEndState: endFunc style: styleFunc duration: time undoable: canUndo inWonderland: aWonderland.
  3573. ! !
  3574.  
  3575. !AliceRelativeAnimation methodsFor: 'management' stamp: 'jsp 7/20/1999 00:18'!
  3576. prologue: currentTime
  3577.     "Extends the AbstractAnimation prologue by saving the start state of the animation."
  3578.  
  3579.     undoable ifTrue: [
  3580.                         (myWonderland getUndoStack)
  3581.                                 push: (AliceUndoAnimation new: (self makeUndoVersion)).
  3582.                     ].
  3583.  
  3584.     (direction = Forward) ifTrue: [
  3585.                                     startState _ getStartStateFunction value.
  3586.                                     endState _ getEndStateFunction value.
  3587.                                 ]
  3588.                         ifFalse: [
  3589.                                     startState _ getStartStateFunction value.
  3590.                                     endState _ getReverseStateFunction value.
  3591.                                 ].
  3592.  
  3593.  
  3594.     super prologue: currentTime.
  3595. ! !
  3596.  
  3597. !AliceRelativeAnimation methodsFor: 'copying' stamp: 'jsp 7/20/1999 00:16'!
  3598. copy
  3599.     "Creates a copy of the animation"
  3600.  
  3601.     | anim |
  3602.  
  3603.     anim _ AliceRelativeAnimation new.
  3604.  
  3605.     anim object: animatedObject
  3606.         update: updateFunction
  3607.         getStartState: getStartStateFunction
  3608.         getEndState: getEndStateFunction
  3609.         getReverseState: getReverseStateFunction 
  3610.         style: styleFunction
  3611.         duration: duration
  3612.         undoable: undoable
  3613.         inWonderland: myWonderland.
  3614.  
  3615.     (direction = Forward) ifFalse: [ anim reverseDirection ].
  3616.  
  3617.     ^ anim.
  3618. ! !
  3619.  
  3620. !AliceRelativeAnimation methodsFor: 'copying' stamp: 'jsp 7/20/1999 00:18'!
  3621. makeUndoVersion
  3622.     "Creates the undo version of an animation"
  3623.  
  3624.     | anim |
  3625.  
  3626.     anim _ AliceRelativeAnimation new.
  3627.  
  3628.     anim object: animatedObject
  3629.         update: updateFunction
  3630.         getStartState: getStartStateFunction
  3631.         getEndState: getEndStateFunction
  3632.         getReverseState: getReverseStateFunction 
  3633.         style: styleFunction
  3634.         duration: 0.5
  3635.         undoable: false
  3636.         inWonderland: myWonderland.
  3637.  
  3638.     anim stop.
  3639.     (direction = Forward) ifTrue: [ anim reverseDirection ].
  3640.  
  3641.     ^ anim.
  3642. ! !
  3643.  
  3644. !AliceRelativeAnimation methodsFor: 'copying' stamp: 'jsp 7/20/1999 00:18'!
  3645. reversed
  3646.     "Creates a reversed version of an animation"
  3647.  
  3648.     | anim |
  3649.  
  3650.     anim _ self copy reverseDirection.
  3651.  
  3652.     ^ anim.
  3653. ! !
  3654.  
  3655. !AliceScheduler methodsFor: 'initialize' stamp: 'jsp 6/7/1999 16:06'!
  3656. initialize
  3657.     "Initialize the scheduler"
  3658.  
  3659.     "The scheduler starts at time 0"
  3660.     currentTime _ 0.
  3661.     elapsedTime _ 0.
  3662.  
  3663.     "The scheduler starts executing at 1:1 time"
  3664.     speed _ 1.
  3665.  
  3666.     "The scheduler starts running"
  3667.     isRunning _ true.
  3668.  
  3669.     "Determine the system time we're starting at"
  3670.     lastSystemTime _ Time millisecondClockValue / 1000.0.
  3671.  
  3672.     "Create the list of items to update"
  3673.     updateList _ OrderedCollection new.
  3674. ! !
  3675.  
  3676. !AliceScheduler methodsFor: 'initialize' stamp: 'jsp 6/7/1999 15:51'!
  3677. reset
  3678.     "Resets the Wonderland time to 0"
  3679.  
  3680.     self initialize.
  3681.  
  3682. ! !
  3683.  
  3684. !AliceScheduler methodsFor: 'accessing' stamp: 'jsp 6/7/1999 15:53'!
  3685. getElapsedTime
  3686.  
  3687.     "Returns the time that elapsed in the last Scheduler tick"
  3688.  
  3689.     ^ elapsedTime.
  3690. ! !
  3691.  
  3692. !AliceScheduler methodsFor: 'accessing' stamp: 'jsp 6/7/1999 15:53'!
  3693. getFPS
  3694.  
  3695.     "Returns the instantaneous frames per second (1 / elapsedTime)"
  3696.  
  3697.     ^ (1.0 / elapsedTime).
  3698. ! !
  3699.  
  3700. !AliceScheduler methodsFor: 'accessing' stamp: 'jsp 6/7/1999 15:53'!
  3701. getTime
  3702.  
  3703.     "Returns the current scheduler time"
  3704.  
  3705.     ^ currentTime.
  3706. ! !
  3707.  
  3708. !AliceScheduler methodsFor: 'accessing' stamp: 'jsp 6/7/1999 15:55'!
  3709. pause
  3710.     "Pause the scheduler. Pauses all script executiong, but any active cameras continue to render."
  3711.  
  3712.     isRunning _ false.
  3713. ! !
  3714.  
  3715. !AliceScheduler methodsFor: 'accessing' stamp: 'jsp 6/7/1999 15:55'!
  3716. resume
  3717.     "If the scheduler was paused, resume it."
  3718.  
  3719.     isRunning ifFalse:     [ isRunning _ true.
  3720.                           lastSystemTime _ (Time millisecondClockValue) / 1000.0.
  3721.                         ].
  3722.  
  3723. ! !
  3724.  
  3725. !AliceScheduler methodsFor: 'accessing' stamp: 'jsp 6/7/1999 15:55'!
  3726. setSpeed: newSpeed
  3727.     "This method sets the speed for the Scheduler. 1 is a 1:1 mapping with clock time, 2 is a 2:1 mapping, etc."
  3728.  
  3729.     (speed > 0) ifTrue: [speed _ newSpeed] ifFalse: [self error: 'Scheduler speed must be greater than 0.'].
  3730.  
  3731. ! !
  3732.  
  3733. !AliceScheduler methodsFor: 'update list maintenance' stamp: 'jsp 6/7/1999 16:05'!
  3734. addUpdateItem: newItem
  3735.     "Add a new item to the scheduler's update list (a running animation, active script, etc"
  3736.  
  3737.     updateList addLast: newItem.
  3738. ! !
  3739.  
  3740. !AliceScheduler methodsFor: 'update list maintenance' stamp: 'jsp 6/7/1999 16:06'!
  3741. removeUpdateItem: anItem
  3742.     "Add a new item to the scheduler's update list (a running animation, active script, etc)"
  3743.  
  3744.     updateList remove: anItem ifAbsent: [].
  3745. ! !
  3746.  
  3747. !AliceScheduler methodsFor: 'ticking' stamp: 'jsp 6/7/1999 16:02'!
  3748. tick
  3749.     "Figure out how much time has elapsed since the last Scheduler tick and update all the scripts"
  3750.  
  3751.     isRunning ifTrue: [
  3752.             elapsedTime _ ((Time millisecondClockValue / 1000.0) - lastSystemTime) * speed.
  3753.  
  3754.             "if elapsedTime is negative the clock rolled over; deal with it"
  3755.             (elapsedTime < 0) ifTrue: [lastSystemTime _ 0. elapsedTime _
  3756.                                         (Time millisecondClockValue) / 1000.0].
  3757.  
  3758.             currentTime _ currentTime + elapsedTime.
  3759.             lastSystemTime _ lastSystemTime + elapsedTime.
  3760.  
  3761.             "Process scripts here"    
  3762.             updateList do: [:item | item update: currentTime.
  3763.                                 (item isDone) ifTrue: [self removeUpdateItem: item]
  3764.                 ].                        ].
  3765. ! !
  3766.  
  3767. !AliceScheduler class methodsFor: 'instance creation' stamp: 'jsp 6/7/1999 15:46'!
  3768. new
  3769.     "Create a new scheduler and initialize it"
  3770.  
  3771.     ^ super new initialize.
  3772. ! !
  3773.  
  3774. !AliceScript methodsFor: 'initialize' stamp: 'jsp 7/20/1999 01:08'!
  3775. initialize: anAliceWorld
  3776.     "Initialize script by assigning the scheduler and putting default values in the instance variables"
  3777.  
  3778.     "Set the script name"
  3779.     scriptName _ 'Unnamed'.
  3780.  
  3781.     "Set the scheduler for this script"
  3782.     myWorld _ anAliceWorld.
  3783.     myScheduler _ myWorld getScheduler.
  3784.  
  3785.     "By default a script contains no commands"
  3786.     myCommands _ OrderedCollection new.
  3787.  
  3788.     "By default there are no active commands"
  3789.     pendingCommands _ OrderedCollection new.
  3790.  
  3791.     "By default there are no active animations"
  3792.     activeAnimations _ OrderedCollection new.
  3793.  
  3794.     "By default scripts run in order (one command after another)"
  3795.     scriptType _ inOrder.
  3796.  
  3797.     "By default the script isn't running"
  3798.     isRunning _ false.
  3799.  
  3800. ! !
  3801.  
  3802. !AliceScript methodsFor: 'accessing' stamp: 'jsp 6/7/1999 21:59'!
  3803. getScriptName
  3804.     "Returns the name of the script"
  3805.  
  3806.     ^ scriptName.
  3807. ! !
  3808.  
  3809. !AliceScript methodsFor: 'accessing' stamp: 'jsp 6/7/1999 16:12'!
  3810. isDone
  3811.     "Returns true if the script is not currently running"
  3812.  
  3813.     ^ isRunning not.
  3814. ! !
  3815.  
  3816. !AliceScript methodsFor: 'accessing' stamp: 'jsp 6/7/1999 15:15'!
  3817. setCommands: commands
  3818.     "Set the commands in the script"
  3819.  
  3820.     myCommands _ commands.
  3821. ! !
  3822.  
  3823. !AliceScript methodsFor: 'accessing' stamp: 'jsp 6/7/1999 21:59'!
  3824. setScriptName: aName
  3825.     "Sets the name of the script"
  3826.  
  3827.     scriptName _ aName.
  3828. ! !
  3829.  
  3830. !AliceScript methodsFor: 'accessing' stamp: 'jsp 6/7/1999 15:14'!
  3831. setScriptType: type
  3832.     "Set the script type (inOrder or Together)"
  3833.  
  3834.     scriptType _ type.
  3835. ! !
  3836.  
  3837. !AliceScript methodsFor: 'executing' stamp: 'jsp 7/20/1999 01:09'!
  3838. start
  3839.     "Start running this script"
  3840.  
  3841.     | result |
  3842.  
  3843.     (scriptType = inOrder)
  3844.         ifTrue: [
  3845.                     pendingCommands _ OrderedCollection new.
  3846.                     1 to: (myCommands size) do: [:i | pendingCommands addLast: i ].
  3847.                 ]
  3848.         ifFalse: [
  3849.                     myCommands do: [:command | result _ command.
  3850.                         result _ Compiler new evaluate: command in: nil to: nil
  3851.                                 notifying: (myWorld getNamespace
  3852.                                             getEvaluationContext) ifFail: [].
  3853.  
  3854.                         myWorld addOutputText: (result printString).
  3855.  
  3856.                         (result isKindOf: Animation)
  3857.                             ifTrue: [ activeAnimations add: result ].
  3858.                                     ].
  3859.                 ].
  3860.  
  3861.  
  3862.     isRunning _ true.
  3863.  
  3864.     "Need to add this script to the scheduler so it gets updated"
  3865.     myScheduler addUpdateItem: self.
  3866.  
  3867.     "Update the script once with the current time"
  3868.     self update: (myScheduler getTime).
  3869. ! !
  3870.  
  3871. !AliceScript methodsFor: 'executing' stamp: 'jsp 6/7/1999 21:38'!
  3872. update: currentTime
  3873.     "Determine how to update this script based on the type of script it is"
  3874.  
  3875.     (scriptType = inOrder)
  3876.         ifTrue: [ self updateInOrder: currentTime ]
  3877.         ifFalse: [ self updateTogether: currentTime ].
  3878.  
  3879. ! !
  3880.  
  3881. !AliceScript methodsFor: 'executing' stamp: 'jsp 6/8/1999 17:33'!
  3882. updateInOrder: currentTime
  3883.     "Update this script assuming that one command runs after the previous command finishes"
  3884.  
  3885.     | nextCommand result |
  3886.  
  3887.     "Update the previous command if it's still active"
  3888.     activeAnimations do: [:anim | anim update: currentTime.
  3889.                                 (anim isDone) ifTrue: [activeAnimations remove: anim ]].
  3890.  
  3891.     "Check if all active animations are complete, if not keep pulling and executing script commands until we hit one that doesn't complete immediately"
  3892.     (activeAnimations isEmpty)
  3893.         ifTrue: [ [ (pendingCommands isEmpty) or: [activeAnimations isEmpty not] ]
  3894.                     whileFalse: [
  3895.                         nextCommand _ myCommands at: (pendingCommands removeFirst).
  3896.  
  3897.                         "evaluate the command in my namespace"
  3898.                         result _ Compiler new evaluate: nextCommand in: nil to: nil
  3899.                                     notifying: (myWorld getNamespace
  3900.                                                 getEvaluationContext) ifFail: [].
  3901.  
  3902.                         myWorld addOutputText: (result printString).
  3903.  
  3904.                         (result isKindOf: Animation)
  3905.                             ifTrue: [ activeAnimations addLast: result ].
  3906.                                 ].
  3907.                 
  3908.                 ((activeAnimations isEmpty) and: [ pendingCommands isEmpty ])
  3909.                     ifTrue: [ isRunning _ false ].
  3910.                 ].
  3911. ! !
  3912.  
  3913. !AliceScript methodsFor: 'executing' stamp: 'jsp 6/7/1999 21:39'!
  3914. updateTogether: currentTime
  3915.     "Update this script assuming that all script commands begin simultaneously"
  3916.  
  3917.     activeAnimations do: [:anim | anim update: currentTime.
  3918.                                 (anim isDone) ifTrue: [activeAnimations remove: anim ]].
  3919.  
  3920.     (activeAnimations isEmpty) ifTrue: [ isRunning _ false ].
  3921.  
  3922.  
  3923. ! !
  3924.  
  3925. !AliceScript class methodsFor: 'instance creation' stamp: 'jsp 6/8/1999 13:36'!
  3926. new: type withCommands: commands in: anAliceWorld
  3927.     "Create a new nameless (lambda) script containing the specified commands"
  3928.  
  3929.     | newScript |
  3930.  
  3931.     newScript _ AliceScript new initialize: anAliceWorld.
  3932.     newScript setScriptType: type.
  3933.     newScript setCommands: commands.
  3934.  
  3935.     ^ newScript.
  3936.  
  3937. ! !
  3938.  
  3939. !AliceTextOutputWindow methodsFor: 'initialization' stamp: 'jsp 7/25/1999 23:11'!
  3940. initialize
  3941.     "Initialize the window for output."
  3942.  
  3943.     super initialize.
  3944.  
  3945.     self color: (Color r: 0.627 g: 0.909 b: 0.972).
  3946.     self openInWorld.
  3947. ! !
  3948.  
  3949. !AliceTextOutputWindow methodsFor: 'output text' stamp: 'jsp 7/25/1999 23:09'!
  3950. addText: aString
  3951.     "Adds the specified string to the output window"
  3952.  
  3953.     | textLength |
  3954.  
  3955.     self setText: ((textMorph contents) , aString) asText.
  3956.  
  3957.     textLength _ textMorph contents size + 1.
  3958.  
  3959.     self selectFrom: textLength to: textLength.
  3960.     self scrollSelectionIntoView.
  3961. ! !
  3962.  
  3963. !AliceTextOutputWindow methodsFor: 'output text' stamp: 'jsp 7/25/1999 23:05'!
  3964. addTextOnNewLine: aString
  3965.     "Adds the specified string to the output window as a new line"
  3966.  
  3967.     | textLength |
  3968.  
  3969.     self setText: ((textMorph contents) , (Character cr asString) , aString) asText.
  3970.  
  3971.     textLength _ textMorph contents size + 1.
  3972.  
  3973.     self selectFrom: textLength to: textLength.
  3974.     self scrollSelectionIntoView.
  3975.  
  3976.  
  3977. ! !
  3978.  
  3979. !AliceUndoAnimation methodsFor: 'accessing' stamp: 'jsp 7/20/1999 00:10'!
  3980. setAnimation: anAnimation
  3981.     "Set wrapped animation."
  3982.  
  3983.     wrappedAnimation _ anAnimation.
  3984. ! !
  3985.  
  3986. !AliceUndoAnimation methodsFor: 'undoing' stamp: 'jsp 7/20/1999 00:10'!
  3987. undoIt
  3988.     "Undo by running the wrapped animation."
  3989.  
  3990.     wrappedAnimation start.
  3991. ! !
  3992.  
  3993. !AliceUndoAnimation class methodsFor: 'instance creation' stamp: 'jsp 7/20/1999 00:11'!
  3994. new: anAnimation
  3995.     "Create a wrapper for undoing an animation"
  3996.  
  3997.     | newUndo |
  3998.  
  3999.     newUndo _ UndoAnimation new.
  4000.     newUndo setAnimation: anAnimation.
  4001.     ^ newUndo.! !
  4002.  
  4003. !AliceUpdateable methodsFor: 'management' stamp: 'jsp 7/20/1999 00:59'!
  4004. setScheduler: scheduler
  4005.     "Set the Scheduler that manages this updateable item"
  4006.  
  4007.     myScheduler _ scheduler.
  4008. ! !
  4009.  
  4010. !AliceUpdateable class methodsFor: 'instance creation' stamp: 'jsp 7/19/1999 21:54'!
  4011. new
  4012.     "Create and initialize a new instance"
  4013.  
  4014.     super new initialize.
  4015. ! !
  4016.  
  4017. !AliceWorld methodsFor: 'temporary' stamp: 'jsp 6/8/1999 22:52'!
  4018. makeActorFrom: filename
  4019.     "Creates a new actor using the specification from the given file"
  4020.  
  4021.     | aFile words line startSubstr index parent name texture meshFile matrix baseActor newActor protoClass actorClass fileVersion |
  4022.  
  4023.     myUndoStack closeStack.
  4024.     words _ (filename findTokens: #.).
  4025.  
  4026.     ((words last) = 'mdl') ifTrue: [
  4027.             aFile _ (CrLfFileStream readOnlyFileNamed: filename) ascii.
  4028.  
  4029.             "First see if we need to create a prototype class for this model"
  4030.             (ActorPrototypeClasses includesKey: (aFile localName))
  4031.                     ifTrue: [ protoClass _ ActorPrototypeClasses at: (aFile localName) ]
  4032.                     ifFalse: [
  4033.                             "Make a new prototype class for this model"
  4034.                             protoClass _ (WonderlandActor newUniqueClassInstVars: ''
  4035.                                                             classInstVars: '').
  4036.                             ActorPrototypeClasses at: (aFile localName) put: protoClass.
  4037.                             ].
  4038.  
  4039.             "Check what version this mdl file is"
  4040.             line _ aFile upTo: (Character cr).
  4041.             line _ aFile upTo: (Character cr).
  4042.             line _ aFile upTo: (Character cr).
  4043.  
  4044.             ((line truncateTo: 7) = 'version')
  4045.                     ifTrue: [ fileVersion _ 1 ]
  4046.                     ifFalse: [ fileVersion _ 0 ].
  4047.  
  4048.             [ line _ aFile upTo: (Character cr).
  4049.               (aFile atEnd) ifTrue: [ true ]
  4050.                           ifFalse: [ words _ line findTokens: '='.
  4051.                                   false ]
  4052.             ] whileFalse: [
  4053.  
  4054.                     "See if we're creating a new object"
  4055.                     (((words size) > 1) and: [ ((words at: 2) beginsWith: ' _MakeObject')
  4056.                                             or: [ (words at: 2) beginsWith: ' Alice.MakeObject' ] ])
  4057.  
  4058.                         ifTrue: [
  4059.                         (fileVersion = 0)
  4060.                             ifTrue: [
  4061.                                 words _ line findTokens: #,.
  4062.                                 parent _ (words at: 2) withBlanksTrimmed.
  4063.                                 name _ (((words at: 3) withBlanksTrimmed)
  4064.                                                     findBetweenSubStrs: '"') at: 1.
  4065.                                     ]
  4066.                             ifFalse: [
  4067.                                 name _ (words at: 1) truncateTo: (((words at: 1) size) - 1).
  4068.                                 parent _ ((words at: 3) findTokens: #,) at: 1.
  4069.                                     ].
  4070.  
  4071.                         "Now pull in the texture to use"
  4072.                         startSubstr _ name , '.SetTexture'.
  4073.                         [(line _ aFile upTo: (Character cr)) beginsWith: startSubstr] whileFalse: [].
  4074.  
  4075.                         texture _ (line findBetweenSubStrs: '"') at: 2.
  4076.                         texture _ (aFile directory pathName), FileDirectory slash, texture.
  4077.  
  4078.                         "Read the composite matrix to use"
  4079.                         startSubstr _ name , '._SetLocalTransformation'.
  4080.                         [(line _ aFile upTo: (Character cr)) beginsWith: startSubstr] whileFalse: [].
  4081.  
  4082.                         matrix _ B3DMatrix4x4 new.
  4083.                         words _ line findBetweenSubStrs: ',()'.
  4084.                         words removeAllSuchThat: [:str | str = ' '].
  4085.  
  4086.                         index _ words size.
  4087.                         4 to: 1 by: -1 do: [:i | 
  4088.                             4 to: 1 by: -1 do: [:j | matrix at: i at: j put: 
  4089.                                         ((words at: index) withBlanksTrimmed) asNumber.
  4090.                                                    index _ index - 1. ]. ].
  4091.  
  4092.                         1 to: 4 do: [:i | index _ matrix at: i at: 4.
  4093.                                        matrix at: i at: 4 put: (matrix at: 4 at: i).
  4094.                                        matrix at: 4 at: i put: index. ].
  4095.  
  4096.                         matrix a14: (matrix a14 negated).
  4097.  
  4098.                         "Read the mesh file to use"
  4099.                         startSubstr _ 'LoadGeometry'.
  4100.                         [(line _ aFile upTo: (Character cr)) beginsWith: startSubstr] whileFalse: [].
  4101.  
  4102.                         meshFile _ (line findBetweenSubStrs: '"') at: 2.
  4103.                         meshFile _ (aFile directory pathName), FileDirectory slash, meshFile.
  4104.  
  4105.                         "Now build the actor name"
  4106.                         words _ name findTokens: '.'.
  4107.                         name _ words last.
  4108.                         name at: 1 put: ((name at: 1) asLowercase).
  4109.  
  4110.                         "Now build the parent name"
  4111.                         parent _ parent copyReplaceAll: '.' with: ' '.
  4112.  
  4113.                         "Now create the object"
  4114.                         (parent = 'None') ifTrue: [
  4115.                                 actorClass _ protoClass newUniqueClassInstVars: '' classInstVars: ''.
  4116.                                 baseActor _ actorClass createFor: self.
  4117.                                 actorClassList addLast: actorClass.
  4118.                                 baseActor setName: name.
  4119.                                 baseActor setTexture: texture.
  4120.                                 baseActor loadMeshFromFile: meshFile.
  4121.                                 baseActor setComposite: matrix.
  4122.                                                 ]  "end base actor creation"
  4123.  
  4124.                                         ifFalse: [
  4125.                                 actorClass _ WonderlandActor newUniqueClassInstVars: ''
  4126.                                                                 classInstVars: ''.
  4127.                                 newActor _ actorClass createFor: self.
  4128.                                 actorClassList addLast: actorClass.
  4129.                                 newActor setName: name.
  4130.                                 parent _ (baseActor getChildNamed: parent).
  4131.                                 newActor reparentTo: parent.
  4132.                                 newActor becomePart.
  4133.                                 newActor setTexture: texture.
  4134.                                 newActor loadMeshFromFile: meshFile.
  4135.                                 newActor setComposite: matrix.
  4136.                                                 ]. "end new actor with parent"
  4137.  
  4138.                                                             ]. "end MakeObject parsing"
  4139.  
  4140.                                             ]. "end file parsing"
  4141.  
  4142.             aFile close.
  4143.             myUndoStack openStack.
  4144.  
  4145.             "Ensure that the new actor's name is unique"
  4146.             name _ self uniqueNameFrom: (baseActor getName).
  4147.             baseActor setName: name.
  4148.             myNamespace at: name put: baseActor.
  4149.  
  4150.             "Add an undo item to undo the creation of this object"
  4151.             myUndoStack push: (UndoAction new: [ baseActor removeFromScene.
  4152.                                                     myNamespace removeKey: name ifAbsent: [].
  4153.                                                   ] ).
  4154.  
  4155.             ^ baseActor.
  4156.                                 ]. " end mdl file parsing"
  4157. ! !
  4158.  
  4159. !AliceWorld methodsFor: 'temporary' stamp: 'jsp 6/8/1999 23:06'!
  4160. makeLight
  4161.     "Create a light of the specified type and add it to the Wonderland"
  4162.  
  4163.     | theLight lightType name |
  4164.  
  4165.     lightType _ positional.
  4166.  
  4167.     "Make sure the user gave us a type of light"
  4168.     [ WonderlandVerifier VerifyLight: lightType ]
  4169.         ifError: [ :msg :rcvr |
  4170.             self reportErrorToUser:
  4171.                 'Squeak could not determine the type of light to create because ', msg.
  4172.             ^ nil ].
  4173.  
  4174.     "The user gave us a valid type type, so proceed"
  4175.     (lightType = ambient)
  4176.         ifTrue: [ theLight _ WonderlandAmbientLight createFor: self. ]
  4177.         ifFalse: [ (lightType = positional)
  4178.             ifTrue: [ theLight _ WonderlandPositionalLight createFor: self. ]
  4179.             ifFalse: [ (lightType = directional)
  4180.                 ifTrue: [ theLight _ WonderlandDirectionalLight createFor: self. ]
  4181.                 ifFalse: [ theLight _ WonderlandSpotLight createFor: self. ]
  4182.                     ]
  4183.                 ].
  4184.  
  4185.     name _ self uniqueNameFrom: 'light'.
  4186.     theLight setName: name.
  4187.     myNamespace at: name put: theLight.
  4188.  
  4189.     lightList addLast: theLight.
  4190.  
  4191.     ^ theLight.
  4192. ! !
  4193.  
  4194. !AliceWorld methodsFor: 'temporary' stamp: 'jsp 6/8/1999 23:05'!
  4195. makeLight: lightType
  4196.     "Create a light of the specified type and add it to the Wonderland"
  4197.  
  4198.     | theLight name |
  4199.  
  4200.     "Make sure the user gave us a type of light"
  4201.     [ WonderlandVerifier VerifyLight: lightType ]
  4202.         ifError: [ :msg :rcvr |
  4203.             self reportErrorToUser:
  4204.                 'Squeak could not determine the type of light to create because ', msg.
  4205.             ^ nil ].
  4206.  
  4207.     "The user gave us a valid type type, so proceed"
  4208.     (lightType = ambient)
  4209.         ifTrue: [ theLight _ WonderlandAmbientLight createFor: self. ]
  4210.         ifFalse: [ (lightType = positional)
  4211.             ifTrue: [ theLight _ WonderlandPositionalLight createFor: self. ]
  4212.             ifFalse: [ (lightType = directional)
  4213.                 ifTrue: [ theLight _ WonderlandDirectionalLight createFor: self. ]
  4214.                 ifFalse: [ theLight _ WonderlandSpotLight createFor: self. ]
  4215.                     ]
  4216.                 ].
  4217.  
  4218.     name _ self uniqueNameFrom: 'light'.
  4219.     theLight setName: name.
  4220.     myNamespace at: name put: theLight.
  4221.  
  4222.     lightList addLast: theLight.
  4223.  
  4224.     ^ theLight.
  4225. ! !
  4226.  
  4227. !AliceWorld methodsFor: 'temporary' stamp: 'jsp 6/8/1999 22:51'!
  4228. renderWonderland: aRenderer
  4229.     "Temporary method"
  4230.  
  4231.     self renderWorld: aRenderer.
  4232.  
  4233. ! !
  4234.  
  4235. !AliceWorld methodsFor: 'initialize-reset-release' stamp: 'jsp 7/25/1999 23:10'!
  4236. initialize
  4237.     "Initialize the Alice world"
  4238.  
  4239.     | defaultCamera |
  4240.  
  4241.     "Initialize this Wonderland's shared namespace"
  4242.     myNamespace _ AliceNamespace new.
  4243.     myNamespace at: 'world' put: self.
  4244.  
  4245.     "Create the Wonderland's scheduler"
  4246.     myScheduler _ AliceScheduler new.
  4247.     myNamespace at: 'scheduler' put: myScheduler.
  4248.  
  4249.     "Initialize the list of actor UniClasses"
  4250.     actorClassList _ OrderedCollection new.
  4251.  
  4252.     "Initialize the shared mesh and texture directories"
  4253.     sharedMeshDict _ Dictionary new.
  4254.     sharedTextureDict _ Dictionary new.
  4255.  
  4256.     "Create an output window for us to dump text to"
  4257.     myTextOutputWindow _ AliceTextOutputWindow new.
  4258.     myTextOutputWindow setText: 'Squeak Alice v2.0.'.
  4259.  
  4260.     cameraList _ OrderedCollection new.
  4261.     lightList _ OrderedCollection new.
  4262.  
  4263.     "-------------------------------"
  4264.  
  4265.     "Create the undo stack for this Wonderland."
  4266.     myUndoStack _ WonderlandUndoStack new.
  4267.  
  4268.     "The scene object is the root of the object tree - all objects in the Wonderland are children (directly or indirectly) of the scene. "
  4269.     myScene _ WonderlandScene newFor: self.
  4270.     myNamespace at: 'scene' put: myScene.
  4271.  
  4272.     "Create the default camera"
  4273.     defaultCamera _ WonderlandCamera createFor: self.
  4274.     cameraList addLast: defaultCamera.
  4275.     myNamespace at: 'camera' put: defaultCamera.
  4276.     myNamespace at: 'cameraWindow' put: (defaultCamera getMorph).
  4277.     defaultCamera setName: 'camera'.
  4278.  
  4279.     myUndoStack reset.
  4280. ! !
  4281.  
  4282. !AliceWorld methodsFor: 'initialize-reset-release' stamp: 'jsp 6/8/1999 22:46'!
  4283. release
  4284.     "This method cleans up the world."
  4285.  
  4286.     "Clean up any uniclasses we created"
  4287.     actorClassList do: [:aClass | aClass removeFromSystem ].
  4288.  
  4289.     "Clean up the output window"
  4290.     myTextOutputWindow delete.
  4291.  
  4292.     "Get rid of our cameras"
  4293.     cameraList do: [:camera | camera release].
  4294. ! !
  4295.  
  4296. !AliceWorld methodsFor: 'initialize-reset-release' stamp: 'jsp 6/8/1999 17:19'!
  4297. reset
  4298.     "Reset this Wonderland"
  4299.  
  4300.     "Initialize this Wonderland's shared namespace"
  4301.     myNamespace _ AliceNamespace new.
  4302.  
  4303.     "Reset the scheduler"
  4304.     myScheduler reset.
  4305.  
  4306.     "Reset the shared mesh and texture directories"
  4307.     sharedMeshDict _ Dictionary new.
  4308.     sharedTextureDict _ Dictionary new.
  4309.  
  4310.     "Reset the list of actor uniclasses"
  4311.     actorClassList do: [:aClass | aClass removeFromSystem ].
  4312.     actorClassList _ OrderedCollection new.
  4313.  
  4314.     "Rebuild the namespace"
  4315.     myNamespace at: 'scheduler' put: myScheduler.
  4316.     myNamespace at: 'world' put: self.
  4317.  
  4318.     "Create a new text output window"
  4319.     myTextOutputWindow setText: 'Reset'.
  4320.  
  4321. ! !
  4322.  
  4323. !AliceWorld methodsFor: 'accessing' stamp: 'jsp 6/8/1999 22:55'!
  4324. getActorClassList
  4325.     "Return the list of actor classes"
  4326.  
  4327.     ^ actorClassList.
  4328. ! !
  4329.  
  4330. !AliceWorld methodsFor: 'accessing' stamp: 'jsp 6/8/1999 22:39'!
  4331. getCameras
  4332.     "Return the list of cameras in the scene"
  4333.  
  4334.     ^ cameraList.
  4335. ! !
  4336.  
  4337. !AliceWorld methodsFor: 'accessing' stamp: 'jsp 6/8/1999 21:36'!
  4338. getDefaultCamera
  4339.     "Return the default camera, which is the camera at the front of the camera list"
  4340.  
  4341.     ^ cameraList first.
  4342. ! !
  4343.  
  4344. !AliceWorld methodsFor: 'accessing' stamp: 'jsp 6/8/1999 22:39'!
  4345. getLights
  4346.     "Return the list of lights in the scene"
  4347.  
  4348.     ^ lightList.
  4349. ! !
  4350.  
  4351. !AliceWorld methodsFor: 'accessing' stamp: 'jsp 6/8/1999 17:38'!
  4352. getNamespace
  4353.     "Return this world's namespace"
  4354.  
  4355.     ^ myNamespace.
  4356. ! !
  4357.  
  4358. !AliceWorld methodsFor: 'accessing' stamp: 'jsp 6/8/1999 21:37'!
  4359. getScene
  4360.     "Return the world's scene"
  4361.  
  4362.     ^ myScene.
  4363.  
  4364. ! !
  4365.  
  4366. !AliceWorld methodsFor: 'accessing' stamp: 'jsp 6/8/1999 17:56'!
  4367. getScheduler
  4368.     "Return this world's scheduler"
  4369.  
  4370.     ^ myScheduler.
  4371. ! !
  4372.  
  4373. !AliceWorld methodsFor: 'accessing' stamp: 'jsp 6/8/1999 21:47'!
  4374. getSharedMeshDict
  4375.     "Return the shared mesh dictionary"
  4376.  
  4377.     ^ sharedMeshDict.
  4378. ! !
  4379.  
  4380. !AliceWorld methodsFor: 'accessing' stamp: 'jsp 6/8/1999 21:47'!
  4381. getSharedTextureDict
  4382.     "Return the shared texture dictionary"
  4383.  
  4384.     ^ sharedTextureDict.
  4385. ! !
  4386.  
  4387. !AliceWorld methodsFor: 'accessing' stamp: 'jsp 6/8/1999 21:38'!
  4388. getUndoStack
  4389.     "Return the world's undo stack"
  4390.  
  4391.     ^ myUndoStack.
  4392.  
  4393. ! !
  4394.  
  4395. !AliceWorld methodsFor: 'creating scripts' stamp: 'jsp 6/8/1999 13:37'!
  4396. doInOrder: commands
  4397.     "Create a nameless inOrder script with the specified commands"
  4398.  
  4399.     ^ AliceScript new: inOrder withCommands: commands in: self.
  4400. ! !
  4401.  
  4402. !AliceWorld methodsFor: 'creating scripts' stamp: 'jsp 6/8/1999 13:37'!
  4403. doTogether: commands
  4404.     "Create a nameless together script with the specified commands"
  4405.  
  4406.     ^ AliceScript new: together withCommands: commands in: self.
  4407. ! !
  4408.  
  4409. !AliceWorld methodsFor: 'creating actors' stamp: 'jsp 6/8/1999 23:12'!
  4410. fixNameFrom: aString
  4411.     "Fix the name to be a valid Smalltalk name (e.g., so that we can compile it as an inst var and accessor message)"
  4412.  
  4413.     | aName |
  4414.  
  4415.     aName _ aString select: [:c | c isAlphaNumeric].
  4416.  
  4417.     "If the name is empty use 'unknown'"
  4418.     aName isEmpty ifTrue:[aName _ 'unknown'].
  4419.  
  4420.     "Make sure the first letter is lowercase"
  4421.     aName first isUppercase
  4422.         ifTrue: [aName _ (aName first asLowercase asString) ,
  4423.                                 (aName copyFrom: 2 to: aName size) ].
  4424.  
  4425.     "Make sure the first letter is a letter, otherwise use 'a' as the first letter"
  4426.     aName first isLetter ifFalse: [aName _ 'a' , aName].
  4427.  
  4428.     ^ aName.
  4429. ! !
  4430.  
  4431. !AliceWorld methodsFor: 'creating actors' stamp: 'jsp 6/8/1999 23:12'!
  4432. uniqueNameFrom: aString
  4433.     "If aName is unique to this world's namespace, returns that name. Otherwise creates a unique variant and returns that."
  4434.  
  4435.     | index aName |
  4436.  
  4437.     aName _ self fixNameFrom: aString.
  4438.  
  4439.     (myNamespace includesKey: aName)
  4440.             ifFalse: [ ^ aName ]
  4441.             ifTrue: [
  4442.                         index _ 2.
  4443.                         [ myNamespace includesKey: (aName , (index asString)) ]
  4444.                             whileTrue: [ index _ index + 1 ].
  4445.                         ^ aName , (index asString).
  4446.                     ].
  4447. ! !
  4448.  
  4449. !AliceWorld methodsFor: 'user feedback' stamp: 'jsp 6/8/1999 17:20'!
  4450. addOutputText: thisText
  4451.     "Appends the given text to the Alice output window"
  4452.  
  4453.     myTextOutputWindow addTextOnNewLine: thisText.
  4454. ! !
  4455.  
  4456. !AliceWorld methodsFor: 'user feedback' stamp: 'jsp 6/8/1999 21:52'!
  4457. reportErrorToUser: errorString
  4458.     "When any object in an Alice World discovers an error it creates an error report and then calls this method to display the error to the user."
  4459.  
  4460.     | errWin tm |
  4461.  
  4462.     errWin _ SystemWindowWithButton labelled: 'Ooops'.
  4463.     errWin openInWorldExtent: 400@100.
  4464.     errWin color: (Color white).
  4465.  
  4466.     tm _ TextMorph new.
  4467.     tm initialize.
  4468.     errWin addMorph: tm.
  4469.  
  4470.     tm color: (Color red).
  4471.     tm contents: errorString wrappedTo: 380.
  4472.     tm position: ((errWin position) + (10@20)).
  4473.     tm lock.
  4474.  
  4475.     errWin height: (tm height) + 30.
  4476.  
  4477.     errorSound play.
  4478.  
  4479.  
  4480.  
  4481. ! !
  4482.  
  4483. !AliceWorld methodsFor: 'undoing actions' stamp: 'jsp 6/8/1999 21:52'!
  4484. undo
  4485.     "Undo the last action the user performed in the Wonderland.  This pulls a block context off the animation stack and executes it."
  4486.  
  4487.     myUndoStack popAndUndo.
  4488. ! !
  4489.  
  4490. !AliceWorld methodsFor: 'drawing' stamp: 'jsp 6/8/1999 21:48'!
  4491. renderWorld: aRenderer
  4492.     "Tell all the objects in the World to render themselves."
  4493.  
  4494.     myScene renderOn: aRenderer.
  4495.  
  4496. ! !
  4497.  
  4498. !AliceWorld methodsFor: 'private' stamp: 'jsp 6/8/1999 22:42'!
  4499. getTextOutputWindow
  4500.     "Returns the current text output window"
  4501.  
  4502.     ^ myTextOutputWindow.
  4503. ! !
  4504.  
  4505. !AliceWorld class methodsFor: 'instance creation' stamp: 'jsp 6/7/1999 22:27'!
  4506. new   "AliceWorld new" 
  4507.     "Create and initialize a new AliceWorld."
  4508.  
  4509.     B3DPrimitiveEngine isAvailable ifFalse: [
  4510.     (self confirm: 'WARNING: This Squeak does not have real 3D support.
  4511. Opening a Wonderland will EXTREMELY time consuming.
  4512. Are you sure you want to do this?
  4513. (NO is probably the right answer :-)') ifFalse: [^ self]].
  4514.  
  4515.     Display depth < 8 ifTrue:
  4516.         [(self confirm: 'The display depth should be set to at least 8 bit.
  4517. Shall I do this now for you?') ifTrue: [Display newDepth: 8]].
  4518.  
  4519.     ^ super new initialize.
  4520.  
  4521. ! !
  4522.  
  4523. !AliceWorld class methodsFor: 'class initialization' stamp: 'jsp 6/7/1999 22:17'!
  4524. initialize
  4525.     "Initialize the AliceWorld class by creating the ActorPrototypeClasses collection"
  4526.  
  4527.     ActorPrototypeClasses _ Dictionary new.
  4528. ! !
  4529.  
  4530. !AliceWorld class methodsFor: 'actor prototype mgmt' stamp: 'jsp 6/7/1999 22:18'!
  4531. removeActorPrototypesFromSystem
  4532.     "Clean out all the actor prototypes - this involves removing those classes from the Smalltalk dictionary"
  4533.  
  4534.     ActorPrototypeClasses do: [:aClass | aClass removeFromSystem ].
  4535.  
  4536.     ActorPrototypeClasses _ Dictionary new.! !
  4537.  
  4538. !AlignmentMorph methodsFor: 'initialization' stamp: 'sw 10/24/1998 14:25'!
  4539. addUpDownArrowsFor: aMorph
  4540.     "Add a column of up and down arrows that serve to send upArrowHit and downArrowHit to aMorph when they're pressed/held down"
  4541.  
  4542.     | holder downArrow upArrow |
  4543.     holder _ Morph new extent: 16 @ 16; beTransparent.
  4544.     downArrow _ ImageMorph new image: (ScriptingSystem formAtKey: 'DownArrow').
  4545.     upArrow _ ImageMorph new image: (ScriptingSystem formAtKey: 'UpArrow').
  4546.     upArrow position: holder bounds topLeft + (2@2).
  4547.     downArrow align: downArrow bottomLeft
  4548.                 with: holder topLeft + (0 @ TileMorph defaultH) + (2@-2).
  4549.     holder addMorph: upArrow.
  4550.     holder addMorph: downArrow.
  4551.     self addMorphBack: holder.
  4552.     upArrow on: #mouseStillDown send: #upArrowHit to: aMorph.
  4553.     downArrow on: #mouseStillDown send: #downArrowHit to: aMorph.! !
  4554.  
  4555. !AlignmentMorph methodsFor: 'initialization'!
  4556. initialize
  4557.  
  4558.     super initialize.
  4559.     borderWidth _ 0.
  4560.     orientation _ #horizontal.    "#horizontal or #vertical  or #free"
  4561.     centering _ #topLeft.        "#topLeft, #center, or #bottomRight"
  4562.     hResizing _ #spaceFill.        "#spaceFill, #shrinkWrap, or #rigid"
  4563.     vResizing _ #spaceFill.        "#spaceFill, #shrinkWrap, or #rigid"
  4564.     inset _ 2.                    "pixels inset within owner's bounds"
  4565.     minCellSize _ 0.                "minimum space between morphs; useful for tables"
  4566.     layoutNeeded _ true.
  4567.     color _ Color r: 0.8 g: 1.0 b: 0.8.
  4568. ! !
  4569.  
  4570. !AlignmentMorph methodsFor: 'initialization' stamp: 'djp 10/24/1999 17:13'!
  4571. openInWindowLabeled: aString inWorld: aWorld
  4572.  
  4573.     inset _ 0.
  4574.     ^super openInWindowLabeled: aString inWorld: aWorld.! !
  4575.  
  4576. !AlignmentMorph methodsFor: 'accessing' stamp: 'panda 4/25/2000 15:44'!
  4577. configureForKids
  4578.     self disableDragNDrop.
  4579.     super configureForKids
  4580. ! !
  4581.  
  4582. !AlignmentMorph methodsFor: 'geometry' stamp: 'di 11/26/1999 22:16'!
  4583. layoutChanged
  4584.  
  4585.     layoutNeeded ifTrue: [^ self].  "In process."
  4586.     layoutNeeded _ true.
  4587.     priorFullBounds _ fullBounds.  "Remember fullBounds"
  4588.     super layoutChanged.
  4589. ! !
  4590.  
  4591. !AlignmentMorph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:47'!
  4592. rootForGrabOf: aMorph
  4593.  
  4594.     | root |
  4595.     self dragNDropEnabled ifFalse: [^ super rootForGrabOf: aMorph].
  4596.     root _ aMorph.
  4597.     [root == self] whileFalse:
  4598.         [root owner = self ifTrue: [^ root].
  4599.         root _ root owner].
  4600.     ^ super rootForGrabOf: aMorph
  4601. ! !
  4602.  
  4603. !AlignmentMorph methodsFor: 'layout' stamp: 'di 11/26/1999 21:37'!
  4604. fullBounds
  4605.     "This is the hook that triggers lazy re-layout of layout morphs. It works because layoutChanged clears the fullBounds cache. Once per cycle, the fullBounds is requested from every morph in the world, and that request gets propagated through the entire submorph hierarchy, causing re-layout where needed. Note that multiple layoutChanges to the same morph can be done with little cost, since the layout is only done when the morph needs to be displayed."
  4606.  
  4607.     fullBounds ifNil: [
  4608.         self resizeIfNeeded.
  4609.         self fixLayout.
  4610.         super fullBounds.  "updates cache"
  4611.         priorFullBounds == nil
  4612.             ifTrue: [self invalidRect: fullBounds]
  4613.             ifFalse: [fullBounds = priorFullBounds
  4614.                     ifFalse: ["report change due to layout"
  4615.                             self invalidRect: (fullBounds merge: priorFullBounds)]].
  4616.         layoutNeeded _ false].
  4617.     ^ super fullBounds
  4618. ! !
  4619.  
  4620. !AlignmentMorph methodsFor: 'menu' stamp: 'panda 4/25/2000 15:47'!
  4621. addCustomMenuItems: aCustomMenu hand: aHandMorph
  4622.  
  4623.     super addCustomMenuItems: aCustomMenu hand: aHandMorph.
  4624.     aCustomMenu add: 'orientation...' action: #chooseOrientation.
  4625.     aCustomMenu add: (self dragNDropEnabled ifTrue: ['close'] ifFalse: ['open']) , ' dragNdrop'
  4626.             action: #toggleDragNDrop.
  4627. ! !
  4628.  
  4629. !AlignmentMorph methodsFor: 'private' stamp: 'sw 5/6/2000 03:09'!
  4630. drawSubmorphsOn: aCanvas
  4631.     ((self hasProperty: #clipToOwnerWidth) and: [owner isWorldOrHandMorph not])
  4632.         ifFalse:
  4633.             [super drawSubmorphsOn: aCanvas]
  4634.         ifTrue:
  4635.             [aCanvas
  4636.                 clipBy:
  4637.                     (self bounds intersect: owner bounds)
  4638.                 during:
  4639.                     [:clippedCanvas | super drawSubmorphsOn: clippedCanvas]]! !
  4640.  
  4641. !AlignmentMorph methodsFor: 'private' stamp: 'jm 11/10/1998 13:14'!
  4642. extraSpacePerMorph
  4643.  
  4644.     | spaceFillingMorphs spaceNeeded extra |
  4645.     spaceFillingMorphs _ 0.
  4646.     spaceNeeded _ 2 * (inset + borderWidth).
  4647.     orientation = #horizontal ifTrue: [
  4648.         submorphs do: [:m |
  4649.             spaceNeeded _ spaceNeeded + (m minWidth max: minCellSize).
  4650.             (m isAlignmentMorph and: [m hResizing = #spaceFill])
  4651.                 ifTrue: [spaceFillingMorphs _ spaceFillingMorphs + 1]].
  4652.         extra _ (bounds width - spaceNeeded) max: 0.
  4653.     ] ifFalse: [
  4654.         submorphs do: [:m |
  4655.             spaceNeeded _ spaceNeeded + (m minHeight max: minCellSize).
  4656.             (m isAlignmentMorph and: [m vResizing = #spaceFill])
  4657.                 ifTrue: [spaceFillingMorphs _ spaceFillingMorphs + 1]].
  4658.         extra _ (bounds height - spaceNeeded) max: 0].
  4659.  
  4660.     (submorphs size <= 1 or: [spaceFillingMorphs <= 1]) ifTrue: [^ extra].
  4661.     ^ extra asFloat / spaceFillingMorphs
  4662. ! !
  4663.  
  4664. !AlignmentMorph methodsFor: 'private' stamp: 'jm 11/10/1998 13:33'!
  4665. fixLayout
  4666.  
  4667.     | extraPerMorph fractionalExtra fractionAccumulator nextPlace extra space |
  4668.     extraPerMorph _ self extraSpacePerMorph asFloat.
  4669.     fractionalExtra _ extraPerMorph fractionPart.
  4670.     extraPerMorph _ extraPerMorph truncated.
  4671.     orientation = #horizontal
  4672.         ifTrue: [nextPlace _ bounds left + inset + borderWidth]
  4673.         ifFalse: [nextPlace _ bounds top + inset + borderWidth].
  4674.  
  4675.     fractionAccumulator _ 0.0.
  4676.     submorphs do: [:m |
  4677.         fractionAccumulator _ fractionAccumulator + fractionalExtra.
  4678.         fractionAccumulator > 0.5
  4679.             ifTrue: [
  4680.                 extra _ extraPerMorph + 1.
  4681.                 fractionAccumulator _ fractionAccumulator - 1.0]
  4682.             ifFalse: [extra _ extraPerMorph].
  4683.         space _ self placeAndSize: m at: nextPlace padding: extra.
  4684.         nextPlace _ nextPlace + space].
  4685. ! !
  4686.  
  4687. !AlignmentMorph methodsFor: 'private' stamp: 'di 11/26/1999 22:11'!
  4688. layoutInWidth: w height: h
  4689.     "Adjust the size of the receiver in its space-filling dimensions during layout. This message is sent to only to layout submorphs."
  4690.  
  4691.     ((hResizing = #spaceFill) and: [bounds width ~= w]) ifTrue: [
  4692.         bounds _ bounds origin extent: (w @ bounds height).
  4693.         self layoutChanged].
  4694.  
  4695.     ((vResizing = #spaceFill) and: [bounds height ~= h]) ifTrue: [
  4696.         bounds _ bounds origin extent: (bounds width @ h).
  4697.         self layoutChanged].
  4698. ! !
  4699.  
  4700. !AlignmentMorph methodsFor: 'private' stamp: 'sw 5/6/2000 02:53'!
  4701. resizeIfNeeded
  4702.     "Resize this morph if it is space-filling or shrink-wrap and its owner is not a layout morph."
  4703.  
  4704.     | newWidth newHeight |
  4705.     newWidth _ bounds width.
  4706.     newHeight _ bounds height.
  4707.  
  4708.     (owner == nil or: [owner isAlignmentMorph not]) ifTrue:
  4709.         "if spaceFill and not in a LayoutMorph, grow to enclose submorphs"
  4710.         [hResizing = #spaceFill ifTrue:
  4711.             [newWidth _ self minWidth max: self bounds width.
  4712.             owner ifNotNil:
  4713.                 [(self hasProperty: #clipToOwnerWidth) ifTrue:
  4714.                     [newWidth _ newWidth min: (owner right - bounds left)]]].
  4715.         vResizing = #spaceFill ifTrue:
  4716.             [newHeight _ self minHeight max: self bounds height]].
  4717.  
  4718.     "if shrinkWrap, adjust size to just fit around submorphs"
  4719.     hResizing = #shrinkWrap ifTrue: [newWidth _ self minWidth].
  4720.     vResizing = #shrinkWrap ifTrue: [newHeight _ self minHeight].
  4721.  
  4722.     ((newWidth ~= bounds width) or: [newHeight ~= bounds height])
  4723.         ifTrue: ["bounds really changed"
  4724.                 bounds _ bounds origin extent: newWidth@newHeight].
  4725. ! !
  4726.  
  4727. !AlignmentMorph methodsFor: 'object fileIn' stamp: 'tk 1/3/2000 16:07'!
  4728. convertbosfcebbochvimol0: varDict bosfcebbochvimolp0: smartRefStrm
  4729.     "These variables are automatically stored into the new instance ('orientation' 'centering' 'hResizing' 'vResizing' 'inset' 'minCellSize' 'openToDragNDrop' 'layoutNeeded' ).
  4730.     This method is for additional changes. Use statements like (foo _ varDict at: 'foo')."
  4731.  
  4732.     "New variables: ('priorFullBounds' )  If a non-nil value is needed, please assign it."
  4733. ! !
  4734.  
  4735. !AlignmentMorph methodsFor: 'object fileIn' stamp: 'mir 5/18/2000 15:21'!
  4736. convertbosfcebbochvimolp0: varDict bosfcebbochvimlp0: smartRefStrm
  4737.     "These variables are automatically stored into the new instance ('bounds' 'owner' 'submorphs' 'fullBounds' 'color' 'extension' 'borderWidth' 'borderColor' 'orientation' 'centering' 'hResizing' 'vResizing' 'inset' 'minCellSize' 'layoutNeeded' 'priorFullBounds' ).
  4738.     This method is for additional changes. Use statements like (foo _ varDict at: 'foo')."
  4739.  
  4740.         "These are going away ('openToDragNDrop' ).  Possibly store their info in another variable?"
  4741.  
  4742.     self enableDragNDrop: (varDict at: 'openToDragNDrop')! !
  4743.  
  4744. !AlignmentMorph class methodsFor: 'instance creation' stamp: 'sw 3/2/1999 14:46'!
  4745. newVariableTransparentSpacer
  4746.     "Answer a space-filling instance of me of the given color."
  4747.  
  4748.     ^ self new
  4749.         hResizing: #spaceFill;
  4750.         vResizing: #spaceFill;
  4751.         inset: 0;
  4752.         borderWidth: 0;
  4753.         color: Color transparent
  4754. ! !
  4755.  
  4756. !AmbientEvent methodsFor: 'as yet unclassified' stamp: 'di 8/3/1998 21:27'!
  4757. morph 
  4758.     ^ morph! !
  4759.  
  4760. !AmbientEvent methodsFor: 'as yet unclassified' stamp: 'di 8/3/1998 20:09'!
  4761. morph: m
  4762.     morph _ m! !
  4763.  
  4764. !AmbientEvent methodsFor: 'as yet unclassified' stamp: 'di 8/4/1998 15:47'!
  4765. occurAtTime: ticks inScorePlayer: player atIndex: index inEventTrack: track secsPerTick: secsPerTick
  4766.     (target == nil or: [selector == nil]) ifTrue:
  4767.         [^ morph encounteredAtTime: ticks inScorePlayer: player atIndex: index inEventTrack: track secsPerTick: secsPerTick].
  4768.     target perform: selector withArguments: arguments! !
  4769.  
  4770. !AmbientEvent methodsFor: 'as yet unclassified' stamp: 'sw 12/30/1998 19:48'!
  4771. relatedPlayer
  4772.     (morph isMemberOf: MovieFrameSyncMorph)
  4773.         ifFalse: [^ nil].
  4774.     ^ morph moviePlayerMorph! !
  4775.  
  4776. !AmbientEvent methodsFor: 'as yet unclassified' stamp: 'di 8/3/1998 20:08'!
  4777. target: t selector: s arguments: a
  4778.     target _ t.
  4779.     selector _ s.
  4780.     arguments _ a.
  4781. ! !
  4782.  
  4783. The Animation class extends the AbstractAnimation class with methods designed for simple (non-composite) animations.
  4784. !
  4785. !Animation methodsFor: 'initialization' stamp: 'jsp 3/9/1999 15:48'!
  4786. object: anObject update: func getStartState: startFunc getEndState: endFunc style: styleFunc duration: time undoable: canUndo inWonderland: aWonderland
  4787.     "This method initializes the Animation with all the information that it needs run."
  4788.  
  4789.     animatedObject _ anObject.
  4790.     updateFunction _ func.
  4791.     styleFunction _ styleFunc.
  4792.     getStartStateFunction _ startFunc.
  4793.     getEndStateFunction _ endFunc.
  4794.     duration _ time.
  4795.     undoable _ canUndo.
  4796.     myScheduler _ aWonderland getScheduler.
  4797.     myWonderland _ aWonderland.
  4798.     loopCount _ 1.
  4799.     direction _ Forward.
  4800.  
  4801.     state _ Waiting.
  4802.     myScheduler addAnimation: self.! !
  4803.  
  4804. !Animation methodsFor: 'management' stamp: 'jsp 3/3/1999 12:02'!
  4805. update: currentTime
  4806.     "Updates the animation using the current Wonderland time"
  4807.  
  4808.     | newState |
  4809.  
  4810.     (state = Waiting) ifTrue: [self prologue: currentTime].
  4811.  
  4812.     (state = Running) ifTrue: [
  4813.                 proportionDone _ styleFunction value: (currentTime - startTime) value: duration.
  4814.                 newState _ startState interpolateTo: endState at: proportionDone.
  4815.                 updateFunction value: newState.
  4816.                 (currentTime >= endTime) ifTrue: [ state _ Finished. ].
  4817.                               ].
  4818.  
  4819.     (state = Finished) ifTrue: [self epilogue: currentTime].! !
  4820.  
  4821. I represent a Squeak front-end to Applescript.  My instances represent either compiled scripts, contexts or both.  My instances maintain separately the original source code from which I was compiled, and then a CompiledApplescript corresponding to that source code in its "current state."  I provide facilities for executing my scripts, alone or in various contexts, as well as for recompiling my script to restore the script to its initial state (if the script bears context information).
  4822.  
  4823. Examples:
  4824.  
  4825.     To execute some text:
  4826.  
  4827.         Applescript doIt: 'beep 3'
  4828.  
  4829.     To compile code into a script object (for MUCH faster execution of repeated tasks, and to maintain state between execution), and then to execute the code:
  4830.  
  4831.         |aVariable|
  4832.         aVariable _ Applescript on: '
  4833.             property sam: 0
  4834.             set sam to sam + 1
  4835.             beep sam'.
  4836.         aVariable doIt
  4837.  
  4838.     Other. somewhat more general operations
  4839.  
  4840.         Applescript doIt: aString mode: anInteger
  4841.         Applescript doIt: aString in: aContext mode: anInteger
  4842.  
  4843.         s _ Applescript on: aString mode: anInteger
  4844.  
  4845.         s doItMode: anInteger
  4846.         s doItIn: aContext
  4847.         s doItIn: aContext mode: anInteger
  4848.         s recompile
  4849.  
  4850.     Also note the examples in the class side of me.
  4851.         !
  4852. !Applescript methodsFor: 'accessing' stamp: 'acg 9/26/1999 01:00'!
  4853. compiledScript
  4854.  
  4855.     ^compiledScript! !
  4856.  
  4857. !Applescript methodsFor: 'accessing' stamp: 'acg 9/27/1999 00:32'!
  4858. modeDocumentation
  4859.  
  4860. "
  4861.     16r0000            kOSAModeNull (kOSANullMode)
  4862.     16r0001            kOSAModePreventGetSource
  4863.     16r0002            kOSAModeCompileIntoContext
  4864.     16r0004            kOSAModeAugmentContext
  4865.     16r0008            kOSAModeDisplayForHumans
  4866.                     kOSAModeNeverInteract
  4867.                     kOSAModeCanInteract
  4868.                     kOSAModeAlwaysInteract
  4869.                     kOSAModeDontReconnect
  4870.     16r0040            kOSAModeCantSwitchLayer
  4871.     16r1000            kOSAModeDoRecord
  4872.     16r4000            kOSAModeDontStoreParent"! !
  4873.  
  4874. !Applescript methodsFor: 'accessing' stamp: 'acg 9/26/1999 00:59'!
  4875. source
  4876.  
  4877.     ^source! !
  4878.  
  4879. !Applescript methodsFor: 'testing' stamp: 'acg 9/26/1999 22:40'!
  4880. hasSource
  4881.  
  4882.     ^self doAsOSAID: [:o | Applescript generic hasSource: o]
  4883. ! !
  4884.  
  4885. !Applescript methodsFor: 'testing' stamp: 'acg 9/26/1999 22:39'!
  4886. isCompiledScript
  4887.  
  4888.     ^self doAsOSAID: [:o | Applescript generic isCompiledScript: o]
  4889. ! !
  4890.  
  4891. !Applescript methodsFor: 'testing' stamp: 'acg 9/26/1999 22:39'!
  4892. isScriptContext
  4893.  
  4894.     ^self doAsOSAID: [:o | Applescript generic isScriptContext: o]
  4895. ! !
  4896.  
  4897. !Applescript methodsFor: 'testing' stamp: 'acg 9/26/1999 22:39'!
  4898. isScriptValue
  4899.  
  4900.     ^self doAsOSAID: [:o | Applescript generic isScriptValue: o]
  4901. ! !
  4902.  
  4903. !Applescript methodsFor: 'testing' stamp: 'acg 9/26/1999 22:39'!
  4904. timesModified
  4905.  
  4906.     ^self doAsOSAID: [:o | Applescript generic timesModified: o]
  4907. ! !
  4908.  
  4909. !Applescript methodsFor: 'interpreting' stamp: 'acg 9/26/1999 21:13'!
  4910. asContextDoOSAID: scptOSAID mode: anInteger
  4911.     "Answer a string corresponding to the result of executing preloaded scptOSAID using my compiledScript as the context, and using mode anInteger.  As a side-effect, update my script information as necessary.  (This routine will not update any stored versions of scptOSAID"
  4912.  
  4913.     ^self 
  4914.         doAsOSAID: 
  4915.             [:contextOSAID |
  4916.              ApplescriptGeneric 
  4917.                 executeAndDisplayOSAID: scptOSAID
  4918.                 in: contextOSAID
  4919.                 mode: anInteger]
  4920.         onErrorDo:         
  4921.             [ApplescriptError 
  4922.                 syntaxErrorFor: (String streamContents:
  4923.                     [:aStream |
  4924.                      aStream 
  4925.                         nextPutAll: (ApplescriptGeneric sourceOfOSAID: scptOSAID); cr; cr;
  4926.                         nextPutAll: '<=== Source Code of Context ===>'; cr;
  4927.                         nextPutAll: source])
  4928.                 withComponent: ApplescriptGeneric]! !
  4929.  
  4930. !Applescript methodsFor: 'interpreting' stamp: 'acg 9/26/1999 20:43'!
  4931. doIt
  4932.     "Answer a string corresponding to the result of executing my script in the default context. mode 0.  As a side-effect, update my script information as necessary."
  4933.  
  4934.     ^self doAsOSAID: [:scptOSAID |
  4935.         ApplescriptGeneric executeAndDisplayOSAID: scptOSAID in: (OSAID new) mode: 0]! !
  4936.  
  4937. !Applescript methodsFor: 'interpreting' stamp: 'acg 9/26/1999 21:22'!
  4938. doItIn: aContext
  4939.     "Answer a string corresponding to the result of executing my script in aContext. mode 0.  As a side-effect, update my script and the aContext information as necessary."
  4940.  
  4941.     ^self doAsOSAID: [:scptContext |
  4942.         aContext asContextDoOSAID: scptContext mode: 0]! !
  4943.  
  4944. !Applescript methodsFor: 'interpreting' stamp: 'acg 9/26/1999 20:43'!
  4945. doItIn: aContext mode: anInteger
  4946.     "Answer a string corresponding to the result of executing my script in aContext. mode anInteger.  As a side-effect, update my script and the aContext information as necessary."
  4947.  
  4948.     ^self doAsOSAID: [:scptContext |
  4949.         aContext asContextDoOSAID: scptContext mode: anInteger]! !
  4950.  
  4951. !Applescript methodsFor: 'interpreting' stamp: 'acg 9/26/1999 20:43'!
  4952. doItMode: anInteger
  4953.     "Answer a string corresponding to the result of executing my script in the default context. mode anInteger.  As a side-effect, update my script information as necessary."
  4954.  
  4955.     ^self doAsOSAID: [:scptOSAID |
  4956.         ApplescriptGeneric 
  4957.             executeAndDisplayOSAID: scptOSAID 
  4958.             in: (OSAID new) 
  4959.             mode: anInteger]! !
  4960.  
  4961. !Applescript methodsFor: 'recompiling' stamp: 'acg 9/26/1999 20:55'!
  4962. recompile
  4963.  
  4964.     self on: source! !
  4965.  
  4966. !Applescript methodsFor: 'recompiling' stamp: 'acg 9/26/1999 20:55'!
  4967. recompileMode: anInteger
  4968.  
  4969.     self on: source mode: anInteger! !
  4970.  
  4971. !Applescript methodsFor: 'printing' stamp: 'acg 9/26/1999 22:52'!
  4972. printOn: aStream
  4973.  
  4974.     aStream nextPutAll: 'an Applescript('.
  4975.     self isCompiledScript ifTrue: [aStream nextPutAll: 'script '].
  4976.     self isScriptContext ifTrue: [aStream nextPutAll: 'context '].
  4977.     aStream 
  4978.         nextPutAll: compiledScript size asString;
  4979.         nextPutAll: ' bytes)'
  4980. ! !
  4981.  
  4982. !Applescript methodsFor: 'private' stamp: 'acg 9/26/1999 20:59'!
  4983. doAsOSAID: aBlock
  4984.     "Answer the result of performing aBlock on my compiledScript, converted to OSAID form.  As a side-effect, update compiledScript to conform to any changes that may have occurred inside the Applescript scripting component."
  4985.  
  4986.     ^self doAsOSAID: aBlock onErrorDo:
  4987.         [ApplescriptError 
  4988.             syntaxErrorFor: source 
  4989.             withComponent: ApplescriptGeneric]! !
  4990.  
  4991. !Applescript methodsFor: 'private' stamp: 'acg 9/27/1999 00:04'!
  4992. doAsOSAID: aCodeBlock onErrorDo: anErrorBlock
  4993.     "Answer the result of performing aBlock on my compiledScript, converted to OSAID form.  As a side-effect, update compiledScript to conform to any changes that may have occurred inside the Applescript scripting component."
  4994.  
  4995.     | anOSAID result |
  4996.     anOSAID _ compiledScript asAEDesc asOSAIDThenDisposeAEDescWith: ApplescriptGeneric.
  4997.     result _ aCodeBlock value: anOSAID.
  4998.     compiledScript _ (anOSAID asCompiledApplescriptWith: ApplescriptGeneric)
  4999.                         ifNil: [compiledScript].
  5000.     anOSAID disposeWith: ApplescriptGeneric.
  5001.     ^result ifNil: [anErrorBlock value]! !
  5002.  
  5003. !Applescript methodsFor: 'private' stamp: 'acg 9/26/1999 21:00'!
  5004. on: aString
  5005.  
  5006.     ^self on: aString mode: 2 onErrorDo: 
  5007.         [ApplescriptError 
  5008.             syntaxErrorFor: aString 
  5009.             withComponent: ApplescriptGeneric]! !
  5010.  
  5011. !Applescript methodsFor: 'private' stamp: 'acg 9/26/1999 20:59'!
  5012. on: aString mode: anInteger
  5013.  
  5014.     ^self on: aString mode: anInteger onErrorDo: 
  5015.         [ApplescriptError 
  5016.             syntaxErrorFor: aString 
  5017.             withComponent: ApplescriptGeneric]! !
  5018.  
  5019. !Applescript methodsFor: 'private' stamp: 'acg 9/26/1999 20:47'!
  5020. on: aString mode: anInteger onErrorDo: aBlock
  5021.  
  5022.     source _ aString.
  5023.     compiledScript _ ApplescriptGeneric compile: aString mode: anInteger.
  5024.     compiledScript ifNil: [^aBlock value].
  5025.     ^self! !
  5026.  
  5027. !Applescript class methodsFor: 'instance creation' stamp: 'acg 9/25/1999 23:36'!
  5028. on: aString
  5029.  
  5030.     ^super new on: aString! !
  5031.  
  5032. !Applescript class methodsFor: 'instance creation' stamp: 'acg 9/26/1999 20:49'!
  5033. on: aString mode: anInteger
  5034.  
  5035.     ^super new on: aString mode: anInteger! !
  5036.  
  5037. !Applescript class methodsFor: 'generic scripting component' stamp: 'acg 9/26/1999 02:19'!
  5038. doIt: aString
  5039.  
  5040.     ^(self on: aString) doIt! !
  5041.  
  5042. !Applescript class methodsFor: 'generic scripting component' stamp: 'acg 9/26/1999 20:50'!
  5043. doIt: aString in: aContext mode: anInteger
  5044.  
  5045.     ^(self on: aString mode: anInteger) doItIn: aContext mode: anInteger! !
  5046.  
  5047. !Applescript class methodsFor: 'generic scripting component' stamp: 'acg 9/26/1999 20:50'!
  5048. doIt: aString mode: anInteger
  5049.  
  5050.     ^(self on: aString mode: anInteger) doItMode: anInteger! !
  5051.  
  5052. !Applescript class methodsFor: 'generic scripting component' stamp: 'acg 9/25/1999 23:43'!
  5053. generic
  5054.     "Answer an ApplescriptInstance (Applescript Generic Scripting Component) that is guaranteed to be active from startUp, but is not (at present) guaranteed to be identical across startups.  Additional instances can be created for multi-threaded applications by using ApplescriptInstance."
  5055.  
  5056.     ^ApplescriptGeneric ifNil:
  5057.         [ApplescriptGeneric _ ApplescriptInstance new]! !
  5058.  
  5059. !Applescript class methodsFor: 'generic scripting component' stamp: 'acg 9/25/1999 23:28'!
  5060. lastError
  5061.  
  5062.     ^self generic lastError! !
  5063.  
  5064. !Applescript class methodsFor: 'sample scripts' stamp: 'acg 9/26/1999 02:16'!
  5065. beep: anInteger
  5066.     "Beep n times"
  5067.  
  5068.     ^self doIt: 'beep ', anInteger asString! !
  5069.  
  5070. !Applescript class methodsFor: 'sample scripts' stamp: 'acg 9/26/1999 02:16'!
  5071. browse: anUrl
  5072.     "Open Microsoft's Web Browser to a page"
  5073.     
  5074.     ^self doIt: 'tell application "Internet Explorer"
  5075.         activate
  5076.         openURL "', anUrl, '"
  5077.     end tell'! !
  5078.  
  5079. !Applescript class methodsFor: 'sample scripts' stamp: 'acg 9/26/1999 02:16'!
  5080. distill
  5081.  
  5082.     Applescript doIt: '
  5083. set prompt to "Select a file to convert to .pdf format"
  5084. set myFile to (choose file with prompt prompt of type "TEXT")
  5085. tell application "Acrobat™ Distiller™ 3.02"
  5086.     activate
  5087.     open myFile
  5088. end tell'! !
  5089.  
  5090. !Applescript class methodsFor: 'sample scripts' stamp: 'acg 9/26/1999 02:16'!
  5091. mandatoryDemo
  5092.     "A mandatory first script"
  5093.  
  5094.     ^self doIt: '3 + 4'! !
  5095.  
  5096. !Applescript class methodsFor: 'sample scripts' stamp: 'acg 9/27/1999 08:12'!
  5097. playQT4Movie
  5098.     "Demonstrate Access to Quicktime"
  5099.  
  5100.     ^Applescript doIt: '-- Play QuickTime File
  5101. -- ©1999 Sal Soghoian, Apple Computer
  5102.  
  5103. property source_folder : ""
  5104. property container_kind : "folder"
  5105. property reset_string : "Pick New Source Folder"
  5106.  
  5107. -- Check the version of QuickTime
  5108. copy my gestaltVersion_info("qtim", 8) to {QT_version, QT_string}
  5109. if the QT_version is less than "0400" then
  5110.     display dialog "This script requires QuickTime 4.0 or higher." & ¬
  5111.         return & return & "The currently installed version is: " & ¬
  5112.         QT_string buttons {"Cancel"} default button 1
  5113. end if
  5114.  
  5115. -- Check the version of the OS
  5116. copy my gestaltVersion_info("sysv", 4) to {system_version, system_string}
  5117. if the system_version is less than "0850" then
  5118.     display dialog "This script requires Mac OS 8.5 or higher." & ¬
  5119.         return & return & "The currently installed version is: " & ¬
  5120.         system_string buttons {"Cancel"} default button 1
  5121. end if
  5122.  
  5123. -- check to see if source folder exists
  5124. try
  5125.     if the source_folder is "" then error
  5126.     set the source_folder to alias (source_folder as text)
  5127. on error
  5128.     set the source_folder to choose_source_folder()
  5129.     if the result is false then return "user canceled"
  5130. end try
  5131.  
  5132. -- set the target folder to the source folder
  5133. set the target_folder to the source_folder
  5134.  
  5135. repeat
  5136.     -- search the target folder for folders or QT files
  5137.     try
  5138.         tell application "Finder"
  5139.             set the item_list to (the name of every item of ¬
  5140.                 the target_folder whose ¬
  5141.                 (creator type is "TVOD") or ¬
  5142.                 (kind is the container_kind)) as list
  5143.             set the item_list to my ASCII_Sort(item_list)
  5144.             set the beginning of the item_list to "Pick New Source Folder"
  5145.         end tell
  5146.     on error
  5147.         beep
  5148.         display dialog "The chosen folder contains no folders or QuickTime files." buttons {"Show Me", "Cancel"} default button 2
  5149.         tell application "Finder"
  5150.             activate
  5151.             open the target_folder
  5152.         end tell
  5153.         return "no items"
  5154.     end try
  5155.     
  5156.     -- prompt the user to pick a folder or file
  5157.     set the chosen_item to choose from list the item_list with prompt ¬
  5158.         "Pick an item:"
  5159.     if the chosen_item is false then return
  5160.     set the chosen_item to the chosen_item as string
  5161.     
  5162.     if the chosen_item is reset_string then
  5163.         set the source_folder to choose_source_folder()
  5164.         if the result is false then return "user canceled"
  5165.         set the target_folder to the source_folder
  5166.     else
  5167.         -- Check the user''s choice to determine whether it''s a file or folder
  5168.         tell application "Finder"
  5169.             if the kind of item chosen_item of the target_folder is the container_kind then
  5170.                 -- The user picked a folder. Set the new target folder and repeat the process.
  5171.                 set the target_folder to folder chosen_item of the the target_folder
  5172.             else
  5173.                 -- The user picked a file. Get the path to the file and exit the repeat.
  5174.                 set the chosen_item to (item chosen_item of the target_folder) as alias
  5175.                 exit repeat
  5176.             end if
  5177.         end tell
  5178.     end if
  5179. end repeat
  5180.  
  5181. -- Find out if the user wants to play the item in the front or back.
  5182. set play_in_background to true
  5183. display dialog "Play the media in the foreground or background?" buttons {"Cancel", "Foreground", "Background"} default button 3
  5184. if the button returned of the result is "Foreground" then set play_in_background to false
  5185.  
  5186. -- Quit the QuickTime Player if it is open
  5187. tell application "Finder"
  5188.     if (the creator type of every process) contains «class TVOD» then ¬
  5189.         tell application "QuickTime Player" to quit
  5190. end tell
  5191.  
  5192. -- Convert the alias to a URL format string
  5193. set this_file to "file:///" & my filepath_to_URL(the chosen_item, true, false)
  5194.  
  5195. -- Tell the QuickTime Player to open the file.
  5196. -- NOTE: to autoplay, Check the Auto-Play preference in the General setting in the QuickTime Player.
  5197. tell application "QuickTime Player"
  5198.     if play_in_background is false then activate
  5199.     open location this_file
  5200. end tell
  5201.  
  5202. on gestaltVersion_info(gestalt_code, string_length)
  5203.     try
  5204.         tell application "Finder" to ¬
  5205.             copy my NumToHex((computer gestalt_code), ¬
  5206.                 string_length) to {a, b, c, d}
  5207.         set the numeric_version to {a, b, c, d} as string
  5208.         if a is "0" then set a to ""
  5209.         set the version_string to (a & b & "." & c & "." & d) as string
  5210.         return {numeric_version, version_string}
  5211.     on error
  5212.         return {"", "unknown"}
  5213.     end try
  5214. end gestaltVersion_info
  5215.  
  5216. on NumToHex(hexData, stringLength)
  5217.     set hexString to {}
  5218.     repeat with i from stringLength to 1 by -1
  5219.         set hexString to ((hexData mod 16) as string) & hexString
  5220.         set hexData to hexData div 16
  5221.     end repeat
  5222.     return (hexString as string)
  5223. end NumToHex
  5224.  
  5225. on choose_source_folder()
  5226.     try
  5227.         set the source_folder to choose folder with prompt ¬
  5228.             "Pick a folder containing Quicktime content:"
  5229.         return the source_folder
  5230.     on error
  5231.         return false
  5232.     end try
  5233. end choose_source_folder
  5234.  
  5235. -- this sub-routine converts a filepath to an encoded URL
  5236. -- My Disk:My Folder:My File
  5237. -- My%20Disk/My%20Folder/My%20File
  5238. on filepath_to_URL(this_file, encode_URL_A, encode_URL_B)
  5239.     set this_file to this_file as text
  5240.     set AppleScript''s text item delimiters to ":"
  5241.     set the path_segments to every text item of this_file
  5242.     repeat with i from 1 to the count of the path_segments
  5243.         set this_segment to item i of the path_segments
  5244.         set item i of the path_segments to ¬
  5245.             my encode_text(this_segment, encode_URL_A, encode_URL_B)
  5246.     end repeat
  5247.     set AppleScript''s text item delimiters to "/"
  5248.     set this_file to the path_segments as string
  5249.     set AppleScript''s text item delimiters to ""
  5250.     return this_file
  5251. end filepath_to_URL
  5252.  
  5253. -- this sub-routine is used to encode text
  5254. on encode_text(this_text, encode_URL_A, encode_URL_B)
  5255.     set the standard_characters to ¬
  5256.         "abcdefghijklmnopqrstuvwxyz0123456789"
  5257.     set the URL_A_chars to "$+!!''/?;&@=#%><{}[]\"~`^\\|*"
  5258.     set the URL_B_chars to ".-_:"
  5259.     set the acceptable_characters to the standard_characters
  5260.     if encode_URL_A is false then ¬
  5261.         set the acceptable_characters to ¬
  5262.             the acceptable_characters & the URL_A_chars
  5263.     if encode_URL_B is false then ¬
  5264.         set the acceptable_characters to ¬
  5265.             the acceptable_characters & the URL_B_chars
  5266.     set the encoded_text to ""
  5267.     repeat with this_char in this_text
  5268.         if this_char is in the acceptable_characters then
  5269.             set the encoded_text to ¬
  5270.                 (the encoded_text & this_char)
  5271.         else
  5272.             set the encoded_text to ¬
  5273.                 (the encoded_text & encode_char(this_char)) as string
  5274.         end if
  5275.     end repeat
  5276.     return the encoded_text
  5277. end encode_text
  5278.  
  5279. -- this sub-routine is used to encode a character
  5280. on encode_char(this_char)
  5281.     set the ASCII_num to (the ASCII number this_char)
  5282.     set the hex_list to ¬
  5283.         {"0", "1", "2", "3", "4", "5", "6", "7", "8", ¬
  5284.             "9", "A", "B", "C", "D", "E", "F"}
  5285.     set x to item ((ASCII_num div 16) + 1) of the hex_list
  5286.     set y to item ((ASCII_num mod 16) + 1) of the hex_list
  5287.     return ("%" & x & y) as string
  5288. end encode_char
  5289.  
  5290. -- This routine sorts a list of strings passed to it
  5291. on ASCII_Sort(my_list)
  5292.     set the index_list to {}
  5293.     set the sorted_list to {}
  5294.     repeat (the number of items in my_list) times
  5295.         set the low_item to ""
  5296.         repeat with i from 1 to (number of items in my_list)
  5297.             if i is not in the index_list then
  5298.                 set this_item to item i of my_list as text
  5299.                 if the low_item is "" then
  5300.                     set the low_item to this_item
  5301.                     set the low_item_index to i
  5302.                 else if this_item comes before the low_item then
  5303.                     set the low_item to this_item
  5304.                     set the low_item_index to i
  5305.                 end if
  5306.             end if
  5307.         end repeat
  5308.         set the end of sorted_list to the low_item
  5309.         set the end of the index_list to the low_item_index
  5310.     end repeat
  5311.     return the sorted_list
  5312. end ASCII_Sort'! !
  5313.  
  5314. !Applescript class methodsFor: 'sample scripts' stamp: 'acg 9/26/1999 02:16'!
  5315. say: aString
  5316.     "Speak the string"
  5317.  
  5318.     ^self doIt: 'say "', aString, '"'
  5319. ! !
  5320.  
  5321. !Applescript class methodsFor: 'sample scripts' stamp: 'acg 9/26/1999 02:16'!
  5322. selectFile
  5323.     "Harness Apple's select file dialog for Squeak"
  5324.  
  5325.     ^self doIt: '(choose file with prompt "Hi guys!!" of type "TEXT") as string'
  5326. ! !
  5327.  
  5328. !Applescript class methodsFor: 'sample scripts' stamp: 'acg 9/26/1999 02:16'!
  5329. selectFolder
  5330.     "Harness Apple's select Folder dialog for Squeak"
  5331.  
  5332.     ^self doIt: '(choose folder with prompt "Hi guys!!") as string'! !
  5333.  
  5334. !Applescript class methodsFor: 'sample scripts' stamp: 'acg 9/21/1999 21:33'!
  5335. silly
  5336.  
  5337.     Applescript say: 'please prez a button for me'.
  5338.     Applescript sillyButtons.
  5339.     Applescript say: 'thank you for pressing the button' ! !
  5340.  
  5341. !Applescript class methodsFor: 'sample scripts' stamp: 'acg 9/26/1999 02:17'!
  5342. sillyButtons
  5343.     "A silly Apple GUI demo"
  5344.  
  5345.     ^self doIt: '
  5346.         display dialog "The Mouse that Roars!!" ',
  5347.             'buttons {"One", "Two", "Three"} default button "One"'
  5348. ! !
  5349.  
  5350. !Applescript class methodsFor: 'sample scripts' stamp: 'acg 9/26/1999 02:17'!
  5351. sillyDialog
  5352.     "A silly Apple GUI demo"
  5353.  
  5354.     self doIt: '
  5355. display dialog "Enter a number between 1 and 10." default answer ""
  5356. set userValue to {text returned of result} as real
  5357. if (userValue < 1) or (userValue > 10) then
  5358.     display dialog "That Value is out of range." buttons {"OK"} default button 1
  5359. else 
  5360.     display dialog "Thanks for playing." buttons {"OK"} default button 1
  5361. end if'
  5362.  
  5363.  
  5364. ! !
  5365.  
  5366. !Applescript class methodsFor: 'sample scripts' stamp: 'acg 9/26/1999 02:17'!
  5367. sillyList
  5368.     "A silly Apple GUI demo"
  5369.  
  5370.     ^Applescript doIt:
  5371.         'choose from list {"dogs", "cats", "lions", "pick the mouse!!"}',
  5372.             'with prompt "hi there"',
  5373.             'default items {"dogs"}',
  5374.             'OK button name "DoIt!!"', 
  5375.             'cancel button name "Chicken!!"'! !
  5376.  
  5377. !Applescript class methodsFor: 'sample scripts' stamp: 'acg 9/26/1999 02:17'!
  5378. sleep
  5379.  
  5380.     ^self doIt: '
  5381. tell application "Finder"
  5382.     sleep
  5383. end tell'
  5384.  
  5385. "Applescript sleep"
  5386. ! !
  5387.  
  5388. !Applescript class methodsFor: 'sample scripts' stamp: 'acg 9/26/1999 02:17'!
  5389. with: voiceString say: contentString
  5390.     "Speak the string"
  5391.  
  5392.     ^self doIt: 'say "', contentString, '" using "', voiceString, '"'
  5393. ! !
  5394.  
  5395. !Applescript class methodsFor: 'initialize-release' stamp: 'acg 9/27/1999 08:35'!
  5396. initialize
  5397.  
  5398.     Smalltalk addToStartUpList: self after: nil.
  5399.     ApplescriptGeneric _ nil.
  5400.     Applescript generic! !
  5401.  
  5402. !Applescript class methodsFor: 'initialize-release' stamp: 'acg 9/25/1999 23:29'!
  5403. reopen
  5404.  
  5405.     ^self generic reopen! !
  5406.  
  5407. !Applescript class methodsFor: 'initialize-release' stamp: 'ar 2/1/2000 15:42'!
  5408. startUp
  5409.     Smalltalk platformName = 'Mac OS' "Can be *really* annoying otherwise"
  5410.         ifTrue:[^self reopen]! !
  5411.  
  5412. I represent a syntax or execution error report for errors encountered when processing Applescripts. As a StringHolder, the string to be viewed is generally the method code or expression containing the error.!
  5413. !ApplescriptError methodsFor: 'as yet unclassified' stamp: 'acg 9/26/1999 02:10'!
  5414. canDiscardEdits
  5415.  
  5416.     ^true! !
  5417.  
  5418. !ApplescriptError methodsFor: 'as yet unclassified' stamp: 'acg 9/26/1999 01:26'!
  5419. code: codeString errorMessage: errString from: fromInteger to: toInteger
  5420.  
  5421.     contents _ codeString.
  5422.     from _ fromInteger.
  5423.     to _ toInteger.
  5424.     errorMessage _ errString! !
  5425.  
  5426. !ApplescriptError methodsFor: 'as yet unclassified' stamp: 'acg 9/26/1999 01:25'!
  5427. contentsSelection
  5428.  
  5429.     ^from to: to! !
  5430.  
  5431. !ApplescriptError methodsFor: 'as yet unclassified' stamp: 'acg 9/26/1999 01:27'!
  5432. list
  5433.  
  5434.     ^Array with: errorMessage! !
  5435.  
  5436. !ApplescriptError methodsFor: 'as yet unclassified' stamp: 'acg 9/26/1999 01:27'!
  5437. listIndex
  5438.  
  5439.     ^1! !
  5440.  
  5441. !ApplescriptError methodsFor: 'as yet unclassified' stamp: 'acg 9/26/1999 22:10'!
  5442. listMenu: aMenu
  5443.  
  5444.     ^aMenu labels: '' lines: #() selections: #()
  5445. ! !
  5446.  
  5447. !ApplescriptError class methodsFor: 'as yet unclassified' stamp: 'acg 9/26/1999 21:00'!
  5448. buildMVCViewOn: aSyntaxError
  5449.     "Answer an MVC view on the given SyntaxError."
  5450.  
  5451.     | topView aListView aCodeView |
  5452.     topView _ StandardSystemView new
  5453.         model: aSyntaxError;
  5454.         label: 'Applescript Error';
  5455.         minimumSize: 380@220.
  5456.  
  5457.     aListView _ PluggableListView on: aSyntaxError
  5458.         list: #list
  5459.         selected: #listIndex
  5460.         changeSelected: nil
  5461.         menu: #listMenu:.
  5462.     aListView window: (0@0 extent: 380@20).
  5463.     topView addSubView: aListView.
  5464.  
  5465.     aCodeView _ PluggableTextView on: aSyntaxError
  5466.         text: #contents
  5467.         accept: nil
  5468.         readSelection: #contentsSelection
  5469.         menu: #codePaneMenu:shifted:.
  5470.     aCodeView window: (0@0 extent: 380@200).
  5471.     topView addSubView: aCodeView below: aListView.
  5472.  
  5473.     ^ topView
  5474. ! !
  5475.  
  5476. !ApplescriptError class methodsFor: 'as yet unclassified' stamp: 'acg 9/26/1999 21:01'!
  5477. buildMorphicViewOn: aSyntaxError
  5478.     "Answer an Morphic view on the given SyntaxError."
  5479.     | window |
  5480.     window _ (SystemWindow labelled: 'Applescript Error') model: aSyntaxError.
  5481.  
  5482.     window addMorph: (PluggableListMorph on: aSyntaxError list: #list
  5483.             selected: #listIndex changeSelected: nil menu: #listMenu:)
  5484.         frame: (0@0 corner: 1@0.15).
  5485.  
  5486.     window addMorph: (PluggableTextMorph on: aSyntaxError text: #contents
  5487.             accept: nil readSelection: #contentsSelection
  5488.             menu: #codePaneMenu:shifted:)
  5489.         frame: (0@0.15 corner: 1@1).
  5490.  
  5491.     ^ window openInWorldExtent: 380@220! !
  5492.  
  5493. !ApplescriptError class methodsFor: 'as yet unclassified' stamp: 'sma 4/30/2000 09:19'!
  5494. open: aSyntaxError
  5495.     "Answer a standard system view whose model is an instance of me."
  5496.  
  5497.     | topView |
  5498.     <primitive: 19> "Simulation guard"
  5499.     Smalltalk isMorphic
  5500.         ifTrue:
  5501.             [self buildMorphicViewOn: aSyntaxError.
  5502.             Project current spawnNewProcessIfThisIsUI: Processor activeProcess.
  5503.             ^ Processor activeProcess suspend].
  5504.     topView _ self buildMVCViewOn: aSyntaxError.
  5505.     topView controller openNoTerminateDisplayAt: Display extent // 2.
  5506.     Cursor normal show.
  5507.     Processor activeProcess suspend! !
  5508.  
  5509. !ApplescriptError class methodsFor: 'as yet unclassified' stamp: 'acg 9/26/1999 01:38'!
  5510. syntaxErrorFor: aString withComponent: anApplescriptInstance
  5511.  
  5512.     |range |
  5513.     range _ anApplescriptInstance lastErrorCodeRange.
  5514.     self open:
  5515.         (super new 
  5516.             code: aString 
  5517.             errorMessage: anApplescriptInstance lastErrorString
  5518.             from: range first
  5519.             to: range last)! !
  5520.  
  5521. I represent an Applescript Scripting Component, derived from the Component Manager.  For more information about Scripting Components, see Inside Macintosh: Interapplication Communications, at:
  5522.  
  5523.     http://developer.apple.com/techpubs/mac/IAC/IAC-2.html.
  5524.  
  5525. Essentially, I represent a record comprising a one-word handle to the scripting component. That handle is passed as a matter of course to almost every important Applescript call.  Accordingly, I am also the repository for most of the primitives for the Applescript/Squeak interface.!
  5526. ]style[(195 54 285)f1,f1Rhttp://developer.apple.com/techpubs/mac/IAC/IAC-2.html;,f1!
  5527. !ApplescriptInstance methodsFor: 'testing' stamp: 'acg 9/26/1999 22:43'!
  5528. hasSource: anOSAID
  5529.  
  5530.     | result |
  5531.     result _ IntegerArray new: 1.
  5532.     (self 
  5533.         primOSAGetScriptInfo: anOSAID 
  5534.         type: (DescType of: 'gsrc')
  5535.         to: result) isZero ifFalse: [^nil].
  5536.     ^(result at: 1) > 0! !
  5537.  
  5538. !ApplescriptInstance methodsFor: 'testing' stamp: 'acg 9/26/1999 22:43'!
  5539. isCompiledScript: anOSAID
  5540.  
  5541.     | result |
  5542.     result _ IntegerArray new: 1.
  5543.     (self 
  5544.         primOSAGetScriptInfo: anOSAID 
  5545.         type: (DescType of: 'cscr')
  5546.         to: result) isZero ifFalse: [^nil].
  5547.     ^(result at: 1) > 0! !
  5548.  
  5549. !ApplescriptInstance methodsFor: 'testing' stamp: 'acg 9/26/1999 22:43'!
  5550. isScriptContext: anOSAID
  5551.  
  5552.     | result |
  5553.     result _ IntegerArray new: 1.
  5554.     (self 
  5555.         primOSAGetScriptInfo: anOSAID 
  5556.         type: (DescType of: 'cntx')
  5557.         to: result) isZero ifFalse: [^nil].
  5558.     ^(result at: 1) > 0! !
  5559.  
  5560. !ApplescriptInstance methodsFor: 'testing' stamp: 'acg 9/26/1999 22:43'!
  5561. isScriptValue: anOSAID
  5562.  
  5563.     | result |
  5564.     result _ IntegerArray new: 1.
  5565.     (self 
  5566.         primOSAGetScriptInfo: anOSAID 
  5567.         type: (DescType of: 'valu')
  5568.         to: result) isZero ifFalse: [^nil].
  5569.     ^(result at: 1) > 0! !
  5570.  
  5571. !ApplescriptInstance methodsFor: 'testing' stamp: 'acg 9/26/1999 22:42'!
  5572. timesModified: anOSAID
  5573.  
  5574.     | result |
  5575.     result _ IntegerArray new: 1.
  5576.     (self 
  5577.         primOSAGetScriptInfo: anOSAID 
  5578.         type: (DescType of: 'modi')
  5579.         to: result) isZero ifFalse: [^nil].
  5580.     ^result at: 1! !
  5581.  
  5582. !ApplescriptInstance methodsFor: 'interpreting' stamp: 'sma 3/15/2000 21:46'!
  5583. compile: aString
  5584.     ^ self compile: aString mode: 0! !
  5585.  
  5586. !ApplescriptInstance methodsFor: 'interpreting' stamp: 'acg 9/27/1999 00:05'!
  5587. compile: aString mode: anInteger
  5588.  
  5589.     | sourceAEDesc objectOSAID objectAEDesc |
  5590.     sourceAEDesc _ AEDesc textTypeOn: aString.
  5591.     (objectOSAID _ self 
  5592.         compileAndDisposeAEDesc: sourceAEDesc 
  5593.         mode: anInteger) ifNil: [^nil].
  5594.     (objectAEDesc _ self 
  5595.         storeAndDisposeOSAID: objectOSAID 
  5596.         type: 'scpt' 
  5597.         mode: anInteger) ifNil: [^nil].
  5598.     ^objectAEDesc asCompiledApplescriptThenDispose
  5599. ! !
  5600.  
  5601. !ApplescriptInstance methodsFor: 'interpreting' stamp: 'acg 9/27/1999 00:05'!
  5602. do: aString
  5603.     "Answer text result of compiling script in null context"
  5604.  
  5605.     ^self doScript: aString in: OSAID new mode: 0! !
  5606.  
  5607. !ApplescriptInstance methodsFor: 'interpreting' stamp: 'acg 9/25/1999 14:14'!
  5608. do: aString in: contextOSAID mode: anInteger
  5609.     "Answer text result of executing Applescript aString in context contexOSAID in mode: anInteger"
  5610.  
  5611.     | source object result |
  5612.     source _ AEDesc textTypeOn: aString.
  5613.     object _ AEDesc new.
  5614.     result _ self    
  5615.         primOSADoScript: source
  5616.         in: contextOSAID
  5617.         mode: anInteger
  5618.         resultType: (DescType of: 'TEXT')
  5619.         to: object.
  5620.     source dispose.
  5621.     result isZero ifFalse: [^nil].
  5622.     ^object asStringThenDispose! !
  5623.  
  5624. !ApplescriptInstance methodsFor: 'interpreting' stamp: 'acg 9/25/1999 14:14'!
  5625. doCompiledScript: aCompiledApplescriptData in: contextOSAID mode: anInteger
  5626.     "Answer text result of executing Applescript aString in context contexOSAID in mode: anInteger"
  5627.  
  5628.     ^self valueOf: aCompiledApplescriptData in: contextOSAID mode: anInteger! !
  5629.  
  5630. !ApplescriptInstance methodsFor: 'interpreting' stamp: 'acg 9/25/1999 14:14'!
  5631. doScript: aString
  5632.     "Answer text result of compiling script in null context"
  5633.  
  5634.     ^self do: aString! !
  5635.  
  5636. !ApplescriptInstance methodsFor: 'interpreting' stamp: 'acg 9/25/1999 14:15'!
  5637. doScript: aString in: contextOSAID mode: anInteger
  5638.     "Answer text result of executing Applescript aString in context contexOSAID in mode: anInteger"
  5639.  
  5640.     ^self do: aString in: contextOSAID mode: anInteger! !
  5641.  
  5642. !ApplescriptInstance methodsFor: 'interpreting' stamp: 'acg 9/27/1999 00:06'!
  5643. scriptingName
  5644. "Answer the name of my generic scripting component"
  5645.  
  5646.     |aeDesc result |
  5647.     aeDesc _ AEDesc new.
  5648.     result _ self primOSAScriptingComponentNameTo: aeDesc.
  5649.     result isZero ifFalse: [^nil].
  5650.     ^aeDesc asStringThenDispose.
  5651. ! !
  5652.  
  5653. !ApplescriptInstance methodsFor: 'interpreting' stamp: 'acg 9/26/1999 21:08'!
  5654. sourceOfOSAID: anOSAID
  5655.  
  5656.     | anAEDesc result |
  5657.     anAEDesc _ AEDesc new.
  5658.     result _ self primOSAGetSource: anOSAID type: 'TEXT' to: anAEDesc.
  5659.     anOSAID disposeWith: self.
  5660.     result isZero ifFalse: [^''].
  5661.     ^anAEDesc asStringThenDispose
  5662.     
  5663.     ! !
  5664.  
  5665. !ApplescriptInstance methodsFor: 'interpreting' stamp: 'acg 9/25/1999 21:53'!
  5666. valueOf: aCompiledApplescript in: contextOSAID mode: anInteger
  5667.     "Answer text result of executing Applescript aString in context contexOSAID in mode: anInteger"
  5668.  
  5669.     | sourceAEDesc sourceOSAID objectOSAID objectAEDesc |
  5670.     sourceAEDesc _ AEDesc scptTypeOn: aCompiledApplescript.
  5671.     sourceOSAID _ self 
  5672.         loadAndDispose: sourceAEDesc 
  5673.         mode: anInteger.
  5674.     sourceOSAID ifNil: [^nil].
  5675.     objectOSAID _ self 
  5676.         executeAndDispose: sourceOSAID
  5677.         in: contextOSAID
  5678.         mode: anInteger.
  5679.     objectOSAID ifNil: [^nil].
  5680.     objectAEDesc _ self
  5681.         displayAndDispose: objectOSAID
  5682.         as: 'TEXT'
  5683.         mode: anInteger.
  5684.     objectAEDesc ifNil: [^nil].
  5685.     ^objectAEDesc asStringThenDispose! !
  5686.  
  5687. !ApplescriptInstance methodsFor: 'error handling' stamp: 'acg 9/25/1999 23:27'!
  5688. lastBriefErrorString
  5689.     "Answer the brief error message for the last error"
  5690.  
  5691.     | aeDesc |
  5692.     aeDesc _ AEDesc new.
  5693.     Applescript generic
  5694.         primOSAScriptError: (DescType of: 'errb')
  5695.         type: (DescType of: 'TEXT')
  5696.         to: aeDesc.
  5697.     ^aeDesc asStringThenDispose! !
  5698.  
  5699. !ApplescriptInstance methodsFor: 'error handling' stamp: 'acg 9/24/1999 00:06'!
  5700. lastError
  5701.  
  5702.     |range|
  5703.     range _ self lastErrorCodeRange.
  5704.     ^String streamContents: [:aStream |
  5705.         aStream
  5706.             nextPutAll: 'Error #';
  5707.             nextPutAll: self lastErrorNumber asString;
  5708.             nextPutAll: ': ';
  5709.             nextPutAll: self lastErrorString;
  5710.             nextPutAll: ' (code ';
  5711.             nextPutAll: range first asString;
  5712.             nextPutAll: ' to ';
  5713.             nextPutAll: range last asString;
  5714.             nextPutAll: ').']! !
  5715.  
  5716. !ApplescriptInstance methodsFor: 'error handling' stamp: 'acg 9/25/1999 23:27'!
  5717. lastErrorCodeRange
  5718.     "Answer the brief error message for the last error"
  5719.  
  5720.     | aeDesc recordDesc data from to |
  5721.     aeDesc _ AEDesc new.
  5722.     recordDesc _ AEDesc new.
  5723.     Applescript generic
  5724.         primOSAScriptError: (DescType of: 'erng')
  5725.         type: (DescType of: 'erng')
  5726.         to: aeDesc.
  5727.     aeDesc
  5728.         primAECoerceDesc: (DescType of: 'reco')
  5729.         to: recordDesc.
  5730.     aeDesc dispose.
  5731.     data _ ByteArray new: 2.
  5732.     recordDesc
  5733.         primAEGetKeyPtr: (DescType of: 'srcs') 
  5734.         type: (DescType of: 'shor')
  5735.         actual: (DescType of: 'shor')
  5736.         to: data.
  5737.     from _ data shortAt: 1 bigEndian: true.
  5738.     recordDesc
  5739.         primAEGetKeyPtr: (DescType of: 'srce') 
  5740.         type: (DescType of: 'shor')
  5741.         actual: (DescType of: 'shor')
  5742.         to: data.
  5743.     to _ data shortAt: 1 bigEndian: true.
  5744.     recordDesc dispose.
  5745.     ^ (from + 1) to: (to + 1)
  5746.  
  5747. ! !
  5748.  
  5749. !ApplescriptInstance methodsFor: 'error handling' stamp: 'acg 9/25/1999 23:27'!
  5750. lastErrorNumber
  5751.     "Answer the error code number of the last error"
  5752.  
  5753.     | aeDesc |
  5754.     aeDesc _ AEDesc new.
  5755.     Applescript generic 
  5756.         primOSAScriptError: (DescType of: 'errn')
  5757.         type: (DescType of: 'shor')
  5758.         to: aeDesc.
  5759.     ^aeDesc asShortThenDispose
  5760. ! !
  5761.  
  5762. !ApplescriptInstance methodsFor: 'error handling' stamp: 'acg 9/25/1999 23:27'!
  5763. lastErrorString
  5764.     "Answer the error message for the last error"
  5765.  
  5766.     | aeDesc |
  5767.     aeDesc _ AEDesc new.
  5768.     Applescript generic
  5769.         primOSAScriptError: (DescType of: 'errs')
  5770.         type: (DescType of: 'TEXT')
  5771.         to: aeDesc.
  5772.     ^aeDesc asStringThenDispose! !
  5773.  
  5774. !ApplescriptInstance methodsFor: 'intermediate operations' stamp: 'acg 9/25/1999 13:55'!
  5775. compileAndDisposeAEDesc: sourceAEDesc mode: anInteger
  5776.  
  5777.     | objectOSAID result |
  5778.     objectOSAID _ OSAID new.
  5779.     result _ self    
  5780.         primOSACompile: sourceAEDesc
  5781.         mode: anInteger
  5782.         to: objectOSAID.
  5783.     sourceAEDesc dispose.
  5784.     result isZero ifFalse: [^nil].
  5785.     ^objectOSAID
  5786. ! !
  5787.  
  5788. !ApplescriptInstance methodsFor: 'intermediate operations' stamp: 'acg 9/26/1999 00:14'!
  5789. displayAndDisposeOSAID: anOSAID as: aString mode: anInteger
  5790.  
  5791.     | anAEDesc result |
  5792.     anOSAID isEmpty ifTrue: [^AEDesc textTypeOn: ''].
  5793.     anAEDesc _ AEDesc new.
  5794.     result _ self 
  5795.         primOSADisplay: anOSAID 
  5796.         as: (DescType of: aString)
  5797.         mode: anInteger 
  5798.         to: anAEDesc.
  5799.     anOSAID disposeWith: self.
  5800.     result isZero ifFalse: 
  5801.         [^nil].
  5802.     ^anAEDesc! !
  5803.  
  5804. !ApplescriptInstance methodsFor: 'intermediate operations' stamp: 'acg 9/26/1999 20:29'!
  5805. executeAndDisplayOSAID: anOSAID in: contextOSAID mode: anInteger
  5806.  
  5807.     | resultOSAID resultAEDesc |
  5808.     resultOSAID _ (self executeOSAID: anOSAID in: contextOSAID mode: anInteger)
  5809.         ifNil: [^nil].
  5810.     resultAEDesc _ (self displayAndDisposeOSAID: resultOSAID as: 'TEXT' mode: anInteger)
  5811.         ifNil: [^nil].
  5812.     ^resultAEDesc asStringThenDispose
  5813.   ! !
  5814.  
  5815. !ApplescriptInstance methodsFor: 'intermediate operations' stamp: 'acg 9/25/1999 09:57'!
  5816. executeAndDisposeOSAID: sourceOSAID in: contextOSAID mode: anInteger
  5817.  
  5818.     | objectOSAID result |
  5819.     objectOSAID _ OSAID new.
  5820.     result _ self 
  5821.         primOSAExecute: sourceOSAID 
  5822.         in: contextOSAID
  5823.         mode: anInteger 
  5824.         to: objectOSAID.
  5825.     sourceOSAID disposeWith: self.
  5826.     result isZero ifFalse: 
  5827.         [^nil].
  5828.     ^objectOSAID! !
  5829.  
  5830. !ApplescriptInstance methodsFor: 'intermediate operations' stamp: 'acg 9/26/1999 00:03'!
  5831. executeOSAID: sourceOSAID in: contextOSAID mode: anInteger
  5832.  
  5833.     | objectOSAID result |
  5834.     objectOSAID _ OSAID new.
  5835.     result _ self 
  5836.         primOSAExecute: sourceOSAID 
  5837.         in: contextOSAID
  5838.         mode: anInteger 
  5839.         to: objectOSAID.
  5840.     result isZero ifFalse: [^nil].
  5841.     ^objectOSAID! !
  5842.  
  5843. !ApplescriptInstance methodsFor: 'intermediate operations' stamp: 'acg 9/25/1999 09:57'!
  5844. loadAndDisposeAEDesc: anAEDesc mode: anInteger
  5845.  
  5846.     | anOSAID result |
  5847.     anOSAID _ OSAID new.
  5848.     result _ self primOSALoad: anAEDesc mode: anInteger to: anOSAID.
  5849.     anAEDesc dispose.
  5850.     result isZero ifFalse: [^nil].
  5851.     ^anOSAID! !
  5852.  
  5853. !ApplescriptInstance methodsFor: 'intermediate operations' stamp: 'acg 9/26/1999 02:59'!
  5854. makeContextAndDiposeOSAID: anOSAID
  5855.     
  5856.     | result contextOSAID contextAEDesc |
  5857.     contextOSAID _ OSAID new.
  5858.     result _ self 
  5859.         primOSAMakeContext: (AEDesc nullType)
  5860.         parent: anOSAID
  5861.         to: contextOSAID.
  5862.     anOSAID dispose.
  5863.     result isZero ifFalse: [^nil].
  5864.     contextAEDesc _ self storeAndDisposeOSAID: contextOSAID type: 'scpt' mode: 0.
  5865.     contextAEDesc ifNil: [^nil].
  5866.     ^ contextAEDesc asCompiledApplescriptThenDispose! !
  5867.  
  5868. !ApplescriptInstance methodsFor: 'intermediate operations' stamp: 'acg 9/26/1999 02:49'!
  5869. makeContextAndDisposeOSAID: anOSAID
  5870.     
  5871.     | result contextAEDesc |
  5872.     contextAEDesc _ AEDesc new.
  5873.     result _ self 
  5874.         primOSAMakeContext: (AEDesc nullType)
  5875.         parent: anOSAID
  5876.         to: contextAEDesc.
  5877.     result isZero ifFalse: [^nil].
  5878.     anOSAID disposeWith: self.
  5879.     ^ contextAEDesc asCompiledApplescriptThenDispose! !
  5880.  
  5881. !ApplescriptInstance methodsFor: 'intermediate operations' stamp: 'acg 9/26/1999 02:58'!
  5882. makeContextOSAID: anOSAID
  5883.     
  5884.     | result contextOSAID contextAEDesc |
  5885.     contextOSAID _ OSAID new.
  5886.     result _ self 
  5887.         primOSAMakeContext: (AEDesc nullType)
  5888.         parent: anOSAID
  5889.         to: contextOSAID.
  5890.     result isZero ifFalse: [^nil].
  5891.     contextAEDesc _ self storeAndDisposeOSAID: contextOSAID type: 'scpt' mode: 0.
  5892.     contextAEDesc ifNil: [^nil].
  5893.     ^ contextAEDesc asCompiledApplescriptThenDispose! !
  5894.  
  5895. !ApplescriptInstance methodsFor: 'intermediate operations' stamp: 'acg 9/25/1999 14:17'!
  5896. storeAndDisposeOSAID: anOSAID type: aString mode: anInteger
  5897.  
  5898.     | theAEDesc result |
  5899.     theAEDesc _ AEDesc new.
  5900.     result _ self    
  5901.         primOSAStore: anOSAID 
  5902.         resultType: (DescType of: aString) 
  5903.         mode: 0  to: (theAEDesc).
  5904.     anOSAID disposeWith: self.
  5905.     result isZero ifFalse: [^nil].
  5906.     ^theAEDesc
  5907.  
  5908. ! !
  5909.  
  5910. !ApplescriptInstance methodsFor: 'intermediate operations' stamp: 'acg 9/25/1999 16:41'!
  5911. storeOSAID: anOSAID type: aString mode: anInteger
  5912.  
  5913.     | theAEDesc result |
  5914.     theAEDesc _ AEDesc new.
  5915.     result _ self    
  5916.         primOSAStore: anOSAID 
  5917.         resultType: (DescType of: aString) 
  5918.         mode: 0  to: (theAEDesc).
  5919.     result isZero ifFalse: [^nil].
  5920.     ^theAEDesc
  5921.  
  5922. ! !
  5923.  
  5924. !ApplescriptInstance methodsFor: 'printing' stamp: 'acg 9/26/1999 00:52'!
  5925. printOn: aStream
  5926.  
  5927.     aStream 
  5928.         nextPutAll: 'an ';
  5929.         nextPutAll: self species asString;
  5930.         nextPutAll: '(';
  5931.         nextPutAll: self scriptingName;
  5932.         nextPutAll: ')'! !
  5933.  
  5934. !ApplescriptInstance methodsFor: 'private' stamp: 'acg 9/21/1999 21:23'!
  5935. initialize
  5936.  
  5937.     super type: 'osa ' subtype: 'scpt'! !
  5938.  
  5939. !ApplescriptInstance methodsFor: 'private' stamp: 'acg 9/22/1999 03:14'!
  5940. primOSACompile: anAEDesc mode: anInteger to: anOSAID
  5941.  
  5942.     <primitive: 'primOSACompile' module: 'TestOSAPlugin'>
  5943.     ^TestOSAPlugin 
  5944.         doPrimitive: 'primOSACompile:mode:to:'
  5945.         withArguments: {anAEDesc. anInteger. anOSAID}! !
  5946.  
  5947. !ApplescriptInstance methodsFor: 'private' stamp: 'acg 9/21/1999 20:57'!
  5948. primOSADisplay: source as: type mode: mode to: result
  5949.  
  5950.     <primitive: 'primOSADisplay' module: 'TestOSAPlugin'>
  5951.     ^TestOSAPlugin 
  5952.         doPrimitive: 'primOSADisplay:as:mode:to:'
  5953.         withArguments: {source. type. mode. result}! !
  5954.  
  5955. !ApplescriptInstance methodsFor: 'private' stamp: 'acg 9/21/1999 20:57'!
  5956. primOSADispose: anOSAID
  5957.  
  5958.     <primitive: 'primOSADispose' module: 'TestOSAPlugin'>
  5959.     ^TestOSAPlugin 
  5960.         doPrimitive: 'primOSADispose:'
  5961.         withArguments: {anOSAID}! !
  5962.  
  5963. !ApplescriptInstance methodsFor: 'private' stamp: 'acg 9/21/1999 20:57'!
  5964. primOSADoScript: source in: context mode: mode resultType: type to: result
  5965.  
  5966.     <primitive: 'primOSADoScript' module: 'TestOSAPlugin'>
  5967.     ^TestOSAPlugin
  5968.         doPrimitive: 'primOSADoScript:in:mode:resultType:to:'
  5969.         withArguments: {source. context. mode. type. result}! !
  5970.  
  5971. !ApplescriptInstance methodsFor: 'private' stamp: 'acg 9/21/1999 20:57'!
  5972. primOSAExecute: script in: context mode: mode to: result
  5973.  
  5974.     <primitive: 'primOSAExecute' module: 'TestOSAPlugin'>
  5975.     ^TestOSAPlugin 
  5976.         doPrimitive: 'primOSAExecute:in:mode:to:'
  5977.         withArguments: { script. context. mode. result }! !
  5978.  
  5979. !ApplescriptInstance methodsFor: 'private' stamp: 'acg 9/26/1999 22:24'!
  5980. primOSAGetScriptInfo: aScriptID type: aDescType to: resultData
  5981.  
  5982.     <primitive: 'primOSAGetScriptInfo' module: 'TestOSAPlugin'>
  5983.     ^TestOSAPlugin 
  5984.         doPrimitive: 'primOSAGetScriptInfo:type:to:'
  5985.         withArguments: {aScriptID. aDescType. resultData}! !
  5986.  
  5987. !ApplescriptInstance methodsFor: 'private' stamp: 'acg 9/25/1999 17:27'!
  5988. primOSAGetSource: aScriptID type: aDescType to: resultData
  5989.  
  5990.     <primitive: 'primOSAGetSource' module: 'TestOSAPlugin'>
  5991.     ^TestOSAPlugin 
  5992.         doPrimitive: 'primOSAGetSource:type:to:'
  5993.         withArguments: {aScriptID. aDescType. resultData}! !
  5994.  
  5995. !ApplescriptInstance methodsFor: 'private' stamp: 'acg 9/22/1999 03:17'!
  5996. primOSALoad: anAEDesc mode: anInteger to: anOSAID
  5997.  
  5998.     <primitive: 'primOSALoad' module: 'TestOSAPlugin'>
  5999.     ^TestOSAPlugin 
  6000.         doPrimitive: 'primOSALoad:mode:to:'
  6001.         withArguments: {anAEDesc. anInteger. anOSAID}! !
  6002.  
  6003. !ApplescriptInstance methodsFor: 'private' stamp: 'acg 9/25/1999 22:56'!
  6004. primOSAMakeContext: name parent: parent to: result
  6005.  
  6006.     <primitive: 'primOSAMakeContext' module: 'TestOSAPlugin'>
  6007.     ^TestOSAPlugin 
  6008.         doPrimitive: 'primOSAMakeContext:parent:to:'
  6009.         withArguments: {name. parent. result}! !
  6010.  
  6011. !ApplescriptInstance methodsFor: 'private' stamp: 'acg 9/23/1999 20:43'!
  6012. primOSAScriptError: anOSType type: aDescType to: anAEDesc
  6013.  
  6014.     <primitive: 'primOSAScriptError' module: 'TestOSAPlugin'>
  6015.     ^TestOSAPlugin 
  6016.         doPrimitive: 'primOSAScriptError:type:to:'
  6017.         withArguments: {anOSType. aDescType. anAEDesc}! !
  6018.  
  6019. !ApplescriptInstance methodsFor: 'private' stamp: 'acg 9/21/1999 20:57'!
  6020. primOSAScriptingComponentNameTo: anAEDesc
  6021.  
  6022.     <primitive: 'primOSAScriptingComponentName' module: 'TestOSAPlugin'>
  6023.     ^TestOSAPlugin 
  6024.         doPrimitive: 'primOSAScriptingComponentNameTo:'
  6025.         withArguments: {anAEDesc}! !
  6026.  
  6027. !ApplescriptInstance methodsFor: 'private' stamp: 'acg 9/22/1999 04:22'!
  6028. primOSAStore: a resultType: b mode: c to: d
  6029.  
  6030.     <primitive: 'primOSAStore' module: 'TestOSAPlugin'>
  6031.     ^TestOSAPlugin 
  6032.         doPrimitive: 'primOSAStore:resultType:mode:to:'
  6033.         withArguments: {a. b. c. d}! !
  6034.  
  6035. !ApplescriptInstance methodsFor: 'private' stamp: 'acg 9/21/1999 21:25'!
  6036. reopen
  6037.  
  6038.     ^super type: 'osa ' subtype: 'scpt'! !
  6039.  
  6040. !ApplescriptInstance class methodsFor: 'as yet unclassified' stamp: 'acg 9/21/1999 21:22'!
  6041. new
  6042.  
  6043.     ^super new initialize! !
  6044.  
  6045. Arcs are an unusual implementation of splines due to Ted Kaehler.  Imagine two lines that meet at a corner. Now imagine two moving points; one moves from the corner to the end on one line, the other moves from the end of the other line in to the corner.  Now imagine a series of lines drawn between those moving points at each step along the way (they form a sort of spider web pattern).  By connecting segments of the intersecting lines, a smooth curve is achieved that is tangent to both of the original lines.  Voila.!
  6046. I present an ArrayedCollection whose elements are objects.!
  6047. !Array methodsFor: 'converting' stamp: 'sma 5/12/2000 17:32'!
  6048. asArray
  6049.     "Answer with the receiver itself."
  6050.  
  6051.     ^ self! !
  6052.  
  6053. !Array methodsFor: 'converting' stamp: 'di 3/28/1999 10:22'!
  6054. elementsExchangeIdentityWith: otherArray
  6055.     "This primitive performs a bulk mutation, causing all pointers to the elements of this array to be replaced by pointers to the corresponding elements of otherArray.  At the same time, all pointers to the elements of otherArray are replaced by pointers to the corresponding elements of this array.  The identityHashes remain with the pointers rather than with the objects so that objects in hashed structures should still be properly indexed after the mutation."
  6056.     <primitive: 128>
  6057.     self primitiveFailed! !
  6058.  
  6059. !Array methodsFor: 'converting' stamp: 'di 3/28/1999 10:23'!
  6060. elementsForwardIdentityTo: otherArray
  6061.     "This primitive performs a bulk mutation, causing all pointers to the elements of this array to be replaced by pointers to the corresponding elements of otherArray.  The identityHashes remain with the pointers rather than with the objects so that the objects in this array should still be properly indexed in any existing hashed structures after the mutation."
  6062.     <primitive: 72>
  6063.     self primitiveFailed! !
  6064.  
  6065. !Array methodsFor: 'printing' stamp: 'sma 5/12/2000 14:11'!
  6066. isLiteral
  6067.     ^ self allSatisfy: [:each | each isLiteral]! !
  6068.  
  6069. !Array methodsFor: 'printing' stamp: 'sma 6/1/2000 09:39'!
  6070. printOn: aStream
  6071.     aStream nextPut: $#.
  6072.     self printElementsOn: aStream! !
  6073.  
  6074. !Array methodsFor: 'private' stamp: 'sma 6/3/2000 21:39'!
  6075. hasLiteral: literal
  6076.     "Answer true if literal is identical to any literal in this array, even 
  6077.     if imbedded in further array structure. This method is only intended 
  6078.     for private use by CompiledMethod hasLiteralSymbol:"
  6079.  
  6080.     | lit |
  6081.     1 to: self size do: 
  6082.         [:index | 
  6083.         (lit _ self at: index) == literal ifTrue: [^ true].
  6084.         (lit class == Array and: [lit hasLiteral: literal]) ifTrue: [^ true]].
  6085.     ^ false! !
  6086.  
  6087. !Array methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 01:42'!
  6088. byteEncode:aStream
  6089.     aStream writeArray:self.
  6090. ! !
  6091.  
  6092. !Array methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 01:55'!
  6093. storeOnStream:aStream
  6094.     self isLiteral ifTrue: [super storeOnStream:aStream] ifFalse:[aStream writeCollection:self].
  6095. ! !
  6096.  
  6097. !Array class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:12'!
  6098. ccg: cg emitLoadFor: aString from: anInteger on: aStream
  6099.  
  6100.     cg emitLoad: aString asIntPtrFrom: anInteger on: aStream! !
  6101.  
  6102. !Array class methodsFor: 'plugin generation' stamp: 'acg 9/19/1999 13:10'!
  6103. ccg: cg prolog: aBlock expr: aString index: anInteger
  6104.  
  6105.     ^cg 
  6106.         ccgLoad: aBlock 
  6107.         expr: aString 
  6108.         asIntPtrFrom: anInteger
  6109.         andThen: (cg ccgValBlock: 'isIndexable')! !
  6110.  
  6111. !Array class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:12'!
  6112. ccgDeclareCForVar: aSymbolOrString
  6113.  
  6114.     ^'int *', aSymbolOrString! !
  6115.  
  6116. !Array class methodsFor: 'brace support' stamp: 'di 11/18/1999 22:53'!
  6117. braceStream: nElements
  6118.     "This method is used in compilation of brace constructs.
  6119.     It MUST NOT be deleted or altered."
  6120.  
  6121.     ^ WriteStream basicNew braceArray: (self new: nElements)
  6122. ! !
  6123.  
  6124. !Array class methodsFor: 'brace support' stamp: 'di 11/19/1999 08:16'!
  6125. braceWith: a
  6126.     "This method is used in compilation of brace constructs.
  6127.     It MUST NOT be deleted or altered."
  6128.  
  6129.     | array |
  6130.     array _ self new: 1.
  6131.     array at: 1 put: a.
  6132.     ^ array! !
  6133.  
  6134. !Array class methodsFor: 'brace support' stamp: 'di 11/19/1999 08:15'!
  6135. braceWith: a with: b 
  6136.     "This method is used in compilation of brace constructs.
  6137.     It MUST NOT be deleted or altered."
  6138.  
  6139.     | array |
  6140.     array _ self new: 2.
  6141.     array at: 1 put: a.
  6142.     array at: 2 put: b.
  6143.     ^ array! !
  6144.  
  6145. !Array class methodsFor: 'brace support' stamp: 'di 11/19/1999 08:17'!
  6146. braceWith: a with: b with: c 
  6147.     "This method is used in compilation of brace constructs.
  6148.     It MUST NOT be deleted or altered."
  6149.  
  6150.     | array |
  6151.     array _ self new: 3.
  6152.     array at: 1 put: a.
  6153.     array at: 2 put: b.
  6154.     array at: 3 put: c.
  6155.     ^ array! !
  6156.  
  6157. !Array class methodsFor: 'brace support' stamp: 'di 11/19/1999 08:17'!
  6158. braceWith: a with: b with: c with: d
  6159.     "This method is used in compilation of brace constructs.
  6160.     It MUST NOT be deleted or altered."
  6161.  
  6162.     | array |
  6163.     array _ self new: 4.
  6164.     array at: 1 put: a.
  6165.     array at: 2 put: b.
  6166.     array at: 3 put: c.
  6167.     array at: 4 put: d.
  6168.     ^ array! !
  6169.  
  6170. !Array class methodsFor: 'brace support' stamp: 'di 11/19/1999 08:16'!
  6171. braceWithNone
  6172.     "This method is used in compilation of brace constructs.
  6173.     It MUST NOT be deleted or altered."
  6174.  
  6175.     ^ self new: 0! !
  6176.  
  6177. A simple 2D-Array implementation. 
  6178.  
  6179. Neither storing nor sorting (otherwise inherited from ArrayedCollection) will work. Neither comparing nor most accessing mehods inherited from Sequenceable collection will work.  Actually, it's a bad idea to inherit this class from collection at all!!!
  6180. !Array2D methodsFor: 'accessing' stamp: 'sma 4/22/2000 18:16'!
  6181. at: x at: y
  6182.     "Answer the element at index x,y."
  6183.  
  6184.     ^ contents at: (self indexX: x y: y)! !
  6185.  
  6186. !Array2D methodsFor: 'accessing' stamp: 'sma 4/22/2000 18:20'!
  6187. at: x at: y add: value
  6188.     "Add value (using #+) to the existing element at index x,y."
  6189.  
  6190.     | index |
  6191.     index _ self indexX: x y: y.
  6192.     ^ contents at: index put: (contents at: index) + value! !
  6193.  
  6194. !Array2D methodsFor: 'accessing' stamp: 'sma 4/22/2000 18:20'!
  6195. at: x at: y put: value
  6196.     "Store value at index x,y and answer it."
  6197.  
  6198.     ^ contents at: (self indexX: x y: y) put: value! !
  6199.  
  6200. !Array2D methodsFor: 'accessing' stamp: 'sma 4/22/2000 18:20'!
  6201. atAllPut: anObject
  6202.     "Put anObject at every one of the receiver's indices."
  6203.  
  6204.     contents atAllPut: anObject! !
  6205.  
  6206. !Array2D methodsFor: 'accessing' stamp: 'sma 4/22/2000 18:22'!
  6207. extent
  6208.     "Answer the receiver's dimensions as point."
  6209.  
  6210.     ^ self width @ self height! !
  6211.  
  6212. !Array2D methodsFor: 'accessing' stamp: 'sma 4/22/2000 18:21'!
  6213. height
  6214.     "Answer the receiver's second dimension."
  6215.  
  6216.     ^ contents size // width! !
  6217.  
  6218. !Array2D methodsFor: 'accessing' stamp: 'sma 4/22/2000 18:22'!
  6219. size
  6220.     ^ contents size! !
  6221.  
  6222. !Array2D methodsFor: 'accessing' stamp: 'sma 4/22/2000 18:22'!
  6223. width
  6224.     "Answer the receiver's first dimension."
  6225.  
  6226.     ^ width! !
  6227.  
  6228. !Array2D methodsFor: 'accessing rows/columns' stamp: 'sma 4/22/2000 18:27'!
  6229. atCol: x
  6230.     "Answer a whole column."
  6231.  
  6232.     | column |
  6233.     column _ contents class new: self height.
  6234.     1 to: self height do: [:index | column at: index put: (self at: x at: index)].
  6235.     ^ column! !
  6236.  
  6237. !Array2D methodsFor: 'accessing rows/columns' stamp: 'sma 4/22/2000 18:30'!
  6238. atCol: x put: aCollection
  6239.     "Put in a whole column."
  6240.  
  6241.     aCollection size = self height ifFalse: [self error: 'wrong column size'].
  6242.     aCollection doWithIndex: [:value :y | self at: x at: y put: value].
  6243.     ^ aCollection! !
  6244.  
  6245. !Array2D methodsFor: 'accessing rows/columns' stamp: 'sma 4/22/2000 18:27'!
  6246. atRow: y
  6247.     "Answer a whole row."
  6248.  
  6249.     (y < 1 or: [y > self height]) ifTrue: [self errorSubscriptBounds: y].
  6250.     ^ contents copyFrom: y - 1 * width + 1 to: y * width! !
  6251.  
  6252. !Array2D methodsFor: 'accessing rows/columns' stamp: 'sma 4/22/2000 18:30'!
  6253. atRow: y put: aCollection
  6254.     "Put in a whole row."
  6255.  
  6256.     aCollection size = self width ifFalse: [self error: 'wrong row size'].
  6257.     aCollection doWithIndex: [:value :x | self at: x at: y put: value].
  6258.     ^ aCollection! !
  6259.  
  6260. !Array2D methodsFor: 'converting' stamp: 'sma 4/22/2000 18:38'!
  6261. asArray
  6262.     ^ contents copy! !
  6263.  
  6264. !Array2D methodsFor: 'copying' stamp: 'sma 4/22/2000 18:37'!
  6265. copy
  6266.     ^ super copy setContents: contents copy! !
  6267.  
  6268. !Array2D methodsFor: 'enumeration' stamp: 'sma 4/22/2000 18:14'!
  6269. do: aBlock
  6270.     "Iterate with X varying most quickly.  6/20/96 tk"
  6271.  
  6272.     contents do: aBlock! !
  6273.  
  6274. !Array2D methodsFor: 'enumeration' stamp: 'sma 4/22/2000 18:39'!
  6275. rowAndColumnValuesDo: aBlock
  6276.     1 to: self width do: [:col |
  6277.         1 to: self height do: [:row |
  6278.             aBlock value: row value: col value: (self at: row at: col)]]! !
  6279.  
  6280. !Array2D methodsFor: 'enumeration' stamp: 'sma 4/22/2000 18:39'!
  6281. rowsAndColumnsDo: aBlock
  6282.     1 to: self width do: [:col |
  6283.         1 to: self height do: [:row |
  6284.             aBlock value: row value: col]]! !
  6285.  
  6286. !Array2D methodsFor: 'private' stamp: 'sma 4/22/2000 18:24'!
  6287. extent: extent fromArray: anArray
  6288.     "Load receiver up from a 1-D array.  X varies most quickly.  6/20/96 tk"
  6289.  
  6290.     extent x * extent y = anArray size ifFalse:
  6291.         [^ self error: 'dimensions don''t match'].
  6292.     width _ extent x.
  6293.     contents _ anArray! !
  6294.  
  6295. !Array2D methodsFor: 'private' stamp: 'sma 4/22/2000 18:16'!
  6296. indexX: x y: y
  6297.     (x < 1 or: [x > width]) ifTrue: [self errorSubscriptBounds: x].
  6298.     ^ y - 1 * width + x! !
  6299.  
  6300. !Array2D methodsFor: 'private' stamp: 'sma 4/22/2000 18:37'!
  6301. setContents: aCollection
  6302.     contents _ aCollection! !
  6303.  
  6304. !Array2D methodsFor: 'private' stamp: 'sma 4/22/2000 18:13'!
  6305. width: x height: y type: collectionClass
  6306.     "Set the number of elements in the first and second dimension.
  6307.     collectionClass can be Array or String or ByteArray."
  6308.  
  6309.     contents == nil ifFalse:
  6310.         [self error: 'No runtime size change yet'].
  6311.         "later move all the elements to the new sized array"
  6312.     width _ x.
  6313.     contents _ collectionClass new: x * y! !
  6314.  
  6315. !Array2D class methodsFor: 'instance creation' stamp: 'sma 4/22/2000 18:40'!
  6316. extent: aPoint
  6317.     ^ self width: aPoint x height: aPoint y! !
  6318.  
  6319. !Array2D class methodsFor: 'instance creation' stamp: 'sma 4/22/2000 18:11'!
  6320. new: size
  6321.     self error: 'Use >>self width: x height: y<< instead'! !
  6322.  
  6323. !Array2D class methodsFor: 'instance creation' stamp: 'sma 4/22/2000 18:10'!
  6324. width: width height: height
  6325.     ^ self basicNew width: width height: height type: Array! !
  6326.  
  6327. !Array2D class methodsFor: 'instance creation' stamp: 'sma 4/22/2000 18:10'!
  6328. width: width height: height type: collectionClass
  6329.     ^ self basicNew width: width height: height type: collectionClass! !
  6330.  
  6331. I am an abstract collection of elements with a fixed range of integers (from 1 to n>=1) as external keys.!
  6332. !ArrayedCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:36'!
  6333. size
  6334.     "Answer how many elements the receiver contains."
  6335.  
  6336.     <primitive: 62>
  6337.     ^ self basicSize! !
  6338.  
  6339. !ArrayedCollection methodsFor: 'adding' stamp: 'sma 5/12/2000 14:09'!
  6340. add: newObject
  6341.     self shouldNotImplement! !
  6342.  
  6343. !ArrayedCollection methodsFor: 'filter streaming' stamp: 'sma 5/12/2000 14:20'!
  6344. flattenOnStream: aStream 
  6345.     aStream writeArrayedCollection: self! !
  6346.  
  6347. !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 5/12/2000 18:18'!
  6348. asSortedArray
  6349.     self isSorted ifTrue: [^ self asArray].
  6350.     ^ super asSortedArray! !
  6351.  
  6352. !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 6/1/2000 11:57'!
  6353. isSorted
  6354.     "Return true if the receiver is sorted by the given criterion.
  6355.     Optimization for isSortedBy: [:a :b | a <= b]."
  6356.  
  6357.     | lastElm elm |
  6358.     self isEmpty ifTrue: [^ true].
  6359.     lastElm _ self first.
  6360.     2 to: self size do: 
  6361.         [:index | 
  6362.         elm _ self at: index.
  6363.         lastElm <= elm ifFalse: [^ false].
  6364.         lastElm _ elm].
  6365.     ^ true! !
  6366.  
  6367. !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 6/1/2000 11:58'!
  6368. isSortedBy: aBlock
  6369.     "Return true if the receiver is sorted by the given criterion."
  6370.  
  6371.     | lastElm elm |
  6372.     self isEmpty ifTrue: [^ true].
  6373.     lastElm _ self first.
  6374.     2 to: self size do: 
  6375.         [:index | 
  6376.         elm _ self at: index.
  6377.         (aBlock value: lastElm value: elm) ifFalse: [^ false].
  6378.         lastElm _ elm].
  6379.     ^ true! !
  6380.  
  6381. !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 5/12/2000 14:28'!
  6382. mergeFirst: first middle: middle last: last into: dst by: aBlock
  6383.     "Private. Merge the sorted ranges [first..middle] and [middle+1..last] 
  6384.     of the receiver into the range [first..last] of dst."
  6385.  
  6386.     | i1 i2 val1 val2 out |
  6387.     i1 _ first.
  6388.     i2 _ middle + 1.
  6389.     val1 _ self at: i1.
  6390.     val2 _ self at: i2.
  6391.     out _ first - 1.  "will be pre-incremented"
  6392.  
  6393.     "select 'lower' half of the elements based on comparator"
  6394.     [(i1 <= middle) and: [i2 <= last]] whileTrue:
  6395.         [(aBlock value: val1 value: val2)
  6396.             ifTrue: [dst at: (out _ out + 1) put: val1.
  6397.                     val1 _ self at: (i1 _ i1 + 1)]
  6398.             ifFalse: [dst at: (out _ out + 1) put: val2.
  6399.                     i2 _ i2 + 1.
  6400.                     i2 <= last ifTrue: [val2 _ self at: i2]]].
  6401.  
  6402.     "copy the remaining elements"
  6403.     i1 <= middle
  6404.         ifTrue: [dst replaceFrom: out + 1 to: last with: self startingAt: i1]
  6405.         ifFalse: [dst replaceFrom: out + 1 to: last with: self startingAt: i2]! !
  6406.  
  6407. !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 5/12/2000 14:25'!
  6408. mergeSortFrom: startIndex to: stopIndex by: aBlock
  6409.     "Sort the given range of indices using the mergesort algorithm.
  6410.     Mergesort is a worst-case O(N log N) sorting algorithm that usually
  6411.     does only half as many comparisons as heapsort or quicksort."
  6412.  
  6413.     "Details: recursively split the range to be sorted into two halves,
  6414.     mergesort each half, then merge the two halves together. An extra 
  6415.     copy of the data is used as temporary storage and successive merge 
  6416.     phases copy data back and forth between the receiver and this copy.
  6417.     The recursion is set up so that the final merge is performed into the
  6418.     receiver, resulting in the receiver being completely sorted."
  6419.  
  6420.     self size <= 1 ifTrue: [^ self].  "nothing to do"
  6421.     startIndex = stopIndex ifTrue: [^ self].
  6422.     self assert: [startIndex >= 1 and: [startIndex < stopIndex]]. "bad start index"
  6423.     self assert: [stopIndex <= self size]. "bad stop index"
  6424.     self
  6425.         mergeSortFrom: startIndex
  6426.         to: stopIndex 
  6427.         src: self clone 
  6428.         dst: self 
  6429.         by: aBlock! !
  6430.  
  6431. !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 5/12/2000 14:26'!
  6432. mergeSortFrom: first to: last src: src dst: dst by: aBlock
  6433.     "Private. Split the range to be sorted in half, sort each half, and 
  6434.     merge the two half-ranges into dst."
  6435.  
  6436.     | middle |
  6437.     first = last ifTrue: [^ self].
  6438.     middle _ (first + last) // 2.
  6439.     self mergeSortFrom: first to: middle src: dst dst: src by: aBlock.
  6440.     self mergeSortFrom: middle + 1 to: last src: dst dst: src by: aBlock.
  6441.     src mergeFirst: first middle: middle last: last into: dst by: aBlock! !
  6442.  
  6443. !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 5/12/2000 14:22'!
  6444. sort
  6445.     "Sort this array into ascending order using the '<=' operator."
  6446.  
  6447.     self sort: [:a :b | a <= b]! !
  6448.  
  6449. !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 5/12/2000 14:21'!
  6450. sort: aSortBlock 
  6451.     "Sort this array using aSortBlock. The block should take two arguments
  6452.     and return true if the first element should preceed the second one."
  6453.  
  6454.     self
  6455.         mergeSortFrom: 1
  6456.         to: self size
  6457.         by: aSortBlock! !
  6458.  
  6459. !ArrayedCollection class methodsFor: 'instance creation' stamp: 'sw 10/24/1998 22:22'!
  6460. with: firstObject with: secondObject with: thirdObject with: fourthObject with: fifthObject with: sixthObject
  6461.     "Answer a new instance of me, containing only the 6 arguments as elements."
  6462.  
  6463.     | newCollection |
  6464.     newCollection _ self new: 6.
  6465.     newCollection at: 1 put: firstObject.
  6466.     newCollection at: 2 put: secondObject.
  6467.     newCollection at: 3 put: thirdObject.
  6468.     newCollection at: 4 put: fourthObject.
  6469.     newCollection at: 5 put: fifthObject.
  6470.     newCollection at: 6 put: sixthObject.
  6471.     ^ newCollection! !
  6472.  
  6473. !ArrayedCollection class methodsFor: 'instance creation' stamp: 'sma 5/12/2000 17:37'!
  6474. withAll: aCollection
  6475.     "Create a new collection containing all the elements from aCollection."
  6476.  
  6477.     ^ (self new: aCollection size) replaceFrom: 1 to: aCollection size with: aCollection! !
  6478.  
  6479. !ArrayedCollection class methodsFor: 'plugin generation' stamp: 'acg 9/20/1999 10:03'!
  6480. ccg: cg generateCoerceToOopFrom: aNode on: aStream
  6481.  
  6482.     self instSize > 0 ifTrue: 
  6483.         [self error: 'cannot auto-coerce arrays with named instance variables'].
  6484.     cg generateCoerceToObjectFromPtr: aNode on: aStream! !
  6485.  
  6486. !ArrayedCollection class methodsFor: 'plugin generation' stamp: 'acg 10/5/1999 06:18'!
  6487. ccg: cg generateCoerceToValueFrom: aNode on: aStream
  6488.  
  6489.     cg 
  6490.         generateCoerceToPtr: (self ccgDeclareCForVar: '')
  6491.         fromObject: aNode on: aStream! !
  6492.  
  6493. !AssignmentNode methodsFor: 'initialize-release' stamp: 'di 3/22/1999 12:00'!
  6494. variable: aVariable value: expression from: encoder
  6495.  
  6496.     (aVariable isMemberOf: MessageAsTempNode)
  6497.         ifTrue: ["Case of remote temp vars"
  6498.                 ^ aVariable store: expression from: encoder].
  6499.     variable _ aVariable.
  6500.     value _ expression! !
  6501.  
  6502. !AssignmentTileMorph methodsFor: 'initialization' stamp: 'sw 1/17/1999 21:10'!
  6503. computeOperatorOrExpression
  6504.     | aSuffix |
  6505.     operatorOrExpression _ (assignmentRoot, assignmentSuffix) asSymbol.
  6506.     aSuffix _ ScriptingSystem wordingForAssignmentSuffix: assignmentSuffix.
  6507.     operatorReadoutString _ assignmentRoot, ' ', aSuffix.
  6508.      self line1: operatorReadoutString.
  6509.     self addArrowsIfAppropriate! !
  6510.  
  6511. !AssignmentTileMorph methodsFor: 'initialization' stamp: 'sw 1/17/1999 21:10'!
  6512. setAssignmentSuffix: aString
  6513.     assignmentSuffix _ aString.
  6514.     self computeOperatorOrExpression.
  6515.     type _ #operator.
  6516.      self line1: (ScriptingSystem wordingForOperator: operatorOrExpression).
  6517.     self addArrowsIfAppropriate; updateLiteralLabel! !
  6518.  
  6519. !AssignmentTileMorph methodsFor: 'arrow' stamp: 'sw 11/22/1999 11:14'!
  6520. addArrowsIfAppropriate
  6521.     "If the receiver's slot is of an appropriate type, add arrows to the tile"
  6522.     (#(number sound boolean menu) includes: dataType)  ifTrue: [self addArrows]! !
  6523.  
  6524. !AssignmentTileMorph methodsFor: 'code generation' stamp: 'sw 12/24/1998 12:33'!
  6525. storeCodeOn: aStream indent: tabCount
  6526.  
  6527.     aStream nextPutAll: ' assign', (assignmentSuffix copyWithout: $:), 'Getter: #'.
  6528.     aStream nextPutAll: (ScriptingSystem getterSelectorFor: assignmentRoot).
  6529.     aStream nextPutAll: ' setter: #'.
  6530.     aStream nextPutAll: (ScriptingSystem setterSelectorFor: assignmentRoot).
  6531.     aStream nextPutAll: ' amt: '.
  6532. ! !
  6533.  
  6534. I represent a pair of associated objects--a key and a value. My instances can serve as entries in a dictionary.!
  6535. !Association methodsFor: 'printing' stamp: 'MPW 1/4/1901 08:31'!
  6536. propertyListOn: aStream
  6537.     aStream write:key; print:'='; write:value.
  6538. ! !
  6539.  
  6540. !Association methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 20:53'!
  6541. byteEncode: aStream
  6542.     aStream writeAssocation:self.! !
  6543.  
  6544. An asynchronous file allows simple file read and write operations to be performed in parallel with other processing. This is useful in multimedia applications that need to stream large amounts of sound or image data from or to a file while doing other work.
  6545. !
  6546. !AsyncFile methodsFor: 'primitives' stamp: 'jm 6/25/1998 07:42'!
  6547. primClose: fHandle
  6548.     "Close this file. Do nothing if primitive fails."
  6549.  
  6550.     <primitive: 540>
  6551. ! !
  6552.  
  6553. !AsyncFile methodsFor: 'primitives' stamp: 'jm 6/25/1998 07:54'!
  6554. primOpen: fileName forWrite: openForWrite semaIndex: semaIndex
  6555.     "Open a file of the given name, and return a handle for that file. Answer the receiver if the primitive succeeds, nil otherwise."
  6556.  
  6557.     <primitive: 541>
  6558.     ^ nil
  6559. ! !
  6560.  
  6561. !AsyncFile methodsFor: 'primitives' stamp: 'jm 6/25/1998 07:28'!
  6562. primReadResult: fHandle intoBuffer: buffer at: startIndex count: count
  6563.     "Copy the result of the last read operation into the given buffer starting at the given index. The buffer may be any sort of bytes or words object, excluding CompiledMethods. Answer the number of bytes read. A negative result means:
  6564.         -1 the last operation is still in progress
  6565.         -2 the last operation encountered an error"
  6566.  
  6567.     <primitive: 542>
  6568.     self primitiveFailed
  6569. ! !
  6570.  
  6571. !AsyncFile methodsFor: 'primitives' stamp: 'di 6/6/2000 14:40'!
  6572. primReadStart: fHandle fPosition: fPosition count: count
  6573.     "Start a read operation of count bytes starting at the given offset in the given file."
  6574.  
  6575.     <primitive: 543>
  6576.     self error: 'READ THE COMMENT FOR THIS METHOD.'
  6577.  
  6578. "NOTE: This method will fail if there is insufficient C heap to allocate an internal buffer of the required size (the value of count).  If you are trying to read a movie file, then the buffer size will be height*width*2 bytes.  Each Squeak image retains a value to be used for this allocation, and it it initially set to 0.  If you are wish to play a 640x480 movie, you need room for a buffer of 640*480*2 = 614400 bytes.  You should execute the following...
  6579.  
  6580.     Smalltalk extraVMMemory: 800000.
  6581.  
  6582. Then save-and-quit, restart, and try to open the movie file again.  If you are using Async files in another way, find out the value of count when this failure occurs (call it NNNN), and instead of the above, execute...
  6583.  
  6584.     Smalltalk extraVMMemory: Smalltalk extraVMMemory + NNNN
  6585.  
  6586. then save-and-quit, restart, and try again.
  6587. "
  6588.  
  6589. ! !
  6590.  
  6591. !AsyncFile methodsFor: 'primitives' stamp: 'jm 6/25/1998 07:27'!
  6592. primWriteResult: fHandle
  6593.     "Answer the number of bytes written. A negative result means:
  6594.         -1 the last operation is still in progress
  6595.         -2 the last operation encountered an error"
  6596.  
  6597.     <primitive: 544>
  6598.     self primitiveFailed
  6599. ! !
  6600.  
  6601. !AsyncFile methodsFor: 'primitives' stamp: 'jm 6/25/1998 08:35'!
  6602. primWriteStart: fHandle fPosition: fPosition fromBuffer: buffer at: startIndex count: count
  6603.     "Start a write operation of count bytes starting at the given index in the given buffer. The buffer may be any sort of bytes or words object, excluding CompiledMethods. The contents of the buffer are copied into an internal buffer immediately, so the buffer can be reused after the write operation has been started. Fail if there is insufficient C heap to allocate an internal buffer of the requested size."
  6604.  
  6605.     <primitive: 545>
  6606.     writeable ifFalse: [^ self error: 'attempt to write a file opened read-only'].
  6607.     self primitiveFailed
  6608. ! !
  6609.  
  6610. !AsyncFile methodsFor: 'as yet unclassified'!
  6611. close
  6612.  
  6613.     fileHandle ifNil: [^ self].  "already closed"
  6614.     self primClose: fileHandle.
  6615.     Smalltalk unregisterExternalObject: semaphore.
  6616.     semaphore _ nil.
  6617.     fileHandle _ nil.
  6618. ! !
  6619.  
  6620. !AsyncFile methodsFor: 'as yet unclassified' stamp: 'di 7/6/1998 10:58'!
  6621. fileHandle
  6622.     ^ fileHandle! !
  6623.  
  6624. !AsyncFile methodsFor: 'as yet unclassified' stamp: 'jm 6/25/1998 07:54'!
  6625. open: fullFileName forWrite: aBoolean
  6626.     "Open a file of the given name, and return a handle for that file. Answer the receiver if the primitive succeeds, nil otherwise.
  6627.     If openForWrite is true, then:
  6628.         if there is no existing file with this name, then create one
  6629.         else open the existing file in read-write mode
  6630.     otherwise:
  6631.         if there is an existing file with this name, then open it read-only
  6632.         else answer nil."
  6633.     "Note: if an exisiting file is opened for writing, it is NOT truncated. If truncation is desired, the file should be deleted before being opened as an asynchronous file."
  6634.     "Note: On some platforms (e.g., Mac), a file can only have one writer at a time."
  6635.  
  6636.     | semaIndex |
  6637.     name _ fullFileName.
  6638.     writeable _ aBoolean.
  6639.     semaphore _ Semaphore new.
  6640.     semaIndex _ Smalltalk registerExternalObject: semaphore.
  6641.     fileHandle _ self primOpen: name forWrite: writeable semaIndex: semaIndex.
  6642.     fileHandle ifNil: [
  6643.         Smalltalk unregisterExternalObject: semaphore.
  6644.         semaphore _ nil.
  6645.         ^ nil].
  6646. ! !
  6647.  
  6648. !AsyncFile methodsFor: 'as yet unclassified' stamp: 'jm 6/25/1998 08:28'!
  6649. readByteCount: byteCount fromFilePosition: fPosition onCompletionDo: aBlock
  6650.     "Start a read operation to read byteCount's from the given position in this file. and fork a process to await its completion. When the operation completes, evaluate the given block. Note that, since the completion block may run asynchronous, the client may need to use a SharedQueue or a semaphore for synchronization."
  6651.  
  6652.     | buffer n |
  6653.     buffer _ String new: byteCount.
  6654.     self primReadStart: fileHandle fPosition: fPosition count: byteCount.
  6655.     "here's the process that awaits the results:"
  6656.     [
  6657.         [    semaphore wait.
  6658.               n _ self primReadResult: fileHandle intoBuffer: buffer at: 1 count: byteCount.
  6659.               n = Busy.
  6660.         ] whileTrue.  "loop while busy in case the semaphore had excess signals"
  6661.         n = Error ifTrue: [^ self error: 'asynchronous read operation failed'].
  6662.         aBlock value: buffer.
  6663.     ] forkAt: Processor userInterruptPriority.
  6664. ! !
  6665.  
  6666. !AsyncFile methodsFor: 'as yet unclassified' stamp: 'jm 6/25/1998 10:07'!
  6667. test: byteCount fileName: fileName
  6668.     "AsyncFile new test: 10000 fileName: 'testData'"
  6669.  
  6670.     | buf1 buf2 bytesWritten bytesRead |
  6671.     buf1 _ String new: byteCount withAll: $x.
  6672.     buf2 _ String new: byteCount.
  6673.     self open: fileName forWrite: true.
  6674.     self primWriteStart: fileHandle
  6675.         fPosition: 0
  6676.         fromBuffer: buf1
  6677.         at: 1
  6678.         count: byteCount.
  6679.     semaphore wait.
  6680.     bytesWritten _ self primWriteResult: fileHandle.
  6681.     self close.
  6682.     
  6683.     self open: fileName forWrite: false.
  6684.     self primReadStart: fileHandle fPosition: 0 count: byteCount.
  6685.     semaphore wait.
  6686.     bytesRead _
  6687.         self primReadResult: fileHandle
  6688.             intoBuffer: buf2
  6689.             at: 1
  6690.             count: byteCount.
  6691.     self close.
  6692.  
  6693.     buf1 = buf2 ifFalse: [self error: 'buffers do not match'].
  6694.     ^ 'wrote ', bytesWritten printString, ' bytes; ',
  6695.        'read ', bytesRead printString, ' bytes'
  6696. ! !
  6697.  
  6698. !AsyncFile methodsFor: 'as yet unclassified' stamp: 'di 7/6/1998 10:58'!
  6699. waitForCompletion
  6700.     semaphore wait! !
  6701.  
  6702. !AsyncFile methodsFor: 'as yet unclassified' stamp: 'jm 6/25/1998 17:28'!
  6703. writeBuffer: buffer atFilePosition: fPosition onCompletionDo: aBlock
  6704.     "Start an operation to write the contents of the buffer at given position in this file, and fork a process to await its completion. When the write completes, evaluate the given block. Note that, since the completion block runs asynchronously, the client may need to use a SharedQueue or a semaphore for synchronization."
  6705.  
  6706.     | n |
  6707.     self primWriteStart: fileHandle
  6708.         fPosition: fPosition
  6709.         fromBuffer: buffer
  6710.         at: 1
  6711.         count: buffer size.
  6712.     "here's the process that awaits the results:"
  6713.     [
  6714.         [    semaphore wait.
  6715.               n _ self primWriteResult: fileHandle.
  6716.               n = Busy.
  6717.         ] whileTrue.  "loop while busy in case the semaphore had excess signals"
  6718.         n = Error ifTrue: [^ self error: 'asynchronous write operation failed'].
  6719.         n = buffer size ifFalse: [^ self error: 'did not write the entire buffer'].
  6720.         aBlock value.
  6721.     ] forkAt: Processor userInterruptPriority.
  6722. ! !
  6723.  
  6724. !AsyncFile class methodsFor: 'class initialization' stamp: 'jm 6/25/1998 17:33'!
  6725. initialize
  6726.     "AsyncFile initialize"
  6727.  
  6728.     "Possible abnormal I/O completion results."
  6729.     Busy _ -1.
  6730.     Error _ -2.
  6731. ! !
  6732.  
  6733. Implements the asynchronous file primtives!
  6734. !AsynchFilePlugin methodsFor: 'initialize-release' stamp: 'ar 5/12/2000 16:52'!
  6735. initialiseModule
  6736.     "Initialise the module"
  6737.     self export: true.
  6738.     ^self cCode: 'asyncFileInit()' inSmalltalk:[true]! !
  6739.  
  6740. !AsynchFilePlugin methodsFor: 'initialize-release' stamp: 'ar 5/12/2000 16:54'!
  6741. shutdownModule
  6742.     "Initialise the module"
  6743.     self export: true.
  6744.     ^self cCode: 'asyncFileShutdown()' inSmalltalk:[true]! !
  6745.  
  6746. !AsynchFilePlugin methodsFor: 'primitives' stamp: 'TPR 2/7/2000 13:01'!
  6747. asyncFileValueOf: oop
  6748.     "Return a pointer to the first byte of the async file record within the given Smalltalk bytes object, or nil if oop is not an async file record."
  6749.  
  6750.     self returnTypeC: 'AsyncFile *'.
  6751.     interpreterProxy success:
  6752.         ((interpreterProxy isIntegerObject: oop) not and:
  6753.          [(interpreterProxy isBytes: oop) and:
  6754.          [(interpreterProxy slotSizeOf: oop) = (self cCode: 'sizeof(AsyncFile)')]]).
  6755.     interpreterProxy failed ifTrue: [^ nil].
  6756.     ^ self cCode: '(AsyncFile *) (oop + 4)'
  6757. ! !
  6758.  
  6759. !AsynchFilePlugin methodsFor: 'primitives' stamp: 'TPR 3/21/2000 17:08'!
  6760. primitiveAsyncFileClose: fh 
  6761.     | f |
  6762.     self var: #f declareC: 'AsyncFile *f'.
  6763.     self primitive: 'primitiveAsyncFileClose'
  6764.         parameters: #(Oop ).
  6765.     f _ self asyncFileValueOf: fh.
  6766.     self asyncFileClose: f! !
  6767.  
  6768. !AsynchFilePlugin methodsFor: 'primitives' stamp: 'TPR 3/21/2000 17:10'!
  6769. primitiveAsyncFileOpen: fileName forWrite: writeFlag semaIndex: semaIndex 
  6770.     | fileNameSize fOop f |
  6771.     self var: #f declareC: 'AsyncFile *f'.
  6772.     self primitive: 'primitiveAsyncFileOpen'
  6773.         parameters: #(String Boolean SmallInteger ).
  6774.  
  6775.     fileNameSize _ interpreterProxy slotSizeOf: (fileName asOop: String).
  6776.     fOop _ interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: (self cCode: 'sizeof(AsyncFile)').
  6777.     f _ self asyncFileValueOf: fOop.
  6778.     interpreterProxy failed ifFalse: [self cCode: 'asyncFileOpen(f, (int)fileName, fileNameSize, writeFlag, semaIndex)'].
  6779.     ^ fOop! !
  6780.  
  6781. !AsynchFilePlugin methodsFor: 'primitives' stamp: 'JMM 8/10/2000 13:04'!
  6782. primitiveAsyncFileReadResult: fhandle intoBuffer: buffer at: start count: num 
  6783.     | bufferSize bufferPtr r f count startIndex |
  6784.     self var: #f declareC: 'AsyncFile *f'.
  6785.     self primitive: 'primitiveAsyncFileReadResult'
  6786.         parameters: #(Oop Oop SmallInteger SmallInteger ).
  6787.     f _ self asyncFileValueOf: fhandle.
  6788.  
  6789.     count _ num.
  6790.     startIndex _ start.
  6791.     bufferSize _ interpreterProxy slotSizeOf: buffer. "in bytes or words"
  6792.     (interpreterProxy isWords: buffer)
  6793.         ifTrue: ["covert word counts to byte counts"
  6794.             count _ count * 4.
  6795.             startIndex _ startIndex - 1 * 4 + 1.
  6796.             bufferSize _ bufferSize * 4].
  6797.     interpreterProxy success: (startIndex >= 1 and: [startIndex + count - 1 <= bufferSize]).
  6798.  
  6799.     bufferPtr _ (self cCoerce: (interpreterProxy firstIndexableField: buffer)
  6800.                 to: 'int')
  6801.                 + startIndex - 1.     "adjust for zero-origin indexing"
  6802.     interpreterProxy failed ifFalse: [r _ self cCode: 'asyncFileReadResult(f, bufferPtr, count)'].
  6803.     ^ r asOop: SmallInteger! !
  6804.  
  6805. !AsynchFilePlugin methodsFor: 'primitives' stamp: 'ar 5/13/2000 16:00'!
  6806. primitiveAsyncFileReadStart: fHandle fPosition: fPosition count: count
  6807.     | f |
  6808.     self var: #f declareC: 'AsyncFile *f'.
  6809.     self primitive: 'primitiveAsyncFileReadStart'
  6810.         parameters: #(Oop SmallInteger SmallInteger).
  6811.     f _ self asyncFileValueOf: fHandle.
  6812.     self cCode: 'asyncFileReadStart(f, fPosition, count)'
  6813. ! !
  6814.  
  6815. !AsynchFilePlugin methodsFor: 'primitives' stamp: 'TPR 2/7/2000 16:09'!
  6816. primitiveAsyncFileWriteResult: fHandle
  6817.  
  6818.     | f r |
  6819.     self var: #f declareC: 'AsyncFile *f'.
  6820.     self primitive: 'primitiveAsyncFileWriteResult'
  6821.         parameters:#(Oop).
  6822.  
  6823.     f _ self asyncFileValueOf: fHandle.
  6824.     r _ self cCode:' asyncFileWriteResult(f)'.
  6825.     ^r asOop: SmallInteger! !
  6826.  
  6827. !AsynchFilePlugin methodsFor: 'primitives' stamp: 'JMM 8/10/2000 13:05'!
  6828. primitiveAsyncFileWriteStart: fHandle fPosition: fPosition fromBuffer: buffer at: start count: num 
  6829.     | f bufferSize bufferPtr count startIndex |
  6830.     self var: #f declareC: 'AsyncFile *f'.
  6831.     self primitive: 'primitiveAsyncFileWriteStart'
  6832.         parameters: #(Oop SmallInteger Oop SmallInteger SmallInteger ).
  6833.     f _ self asyncFileValueOf: fHandle.
  6834.     interpreterProxy failed ifTrue: [^ nil].
  6835.  
  6836.     count _ num.
  6837.     startIndex _ start.
  6838.     bufferSize _ interpreterProxy slotSizeOf: buffer.    "in bytes or words"
  6839.     (interpreterProxy isWords: buffer)
  6840.         ifTrue: ["covert word counts to byte counts"
  6841.             count _ count * 4.
  6842.             startIndex _ startIndex - 1 * 4 + 1.
  6843.             bufferSize _ bufferSize * 4].
  6844.     interpreterProxy success: (startIndex >= 1 and: [startIndex + count - 1 <= bufferSize]).
  6845.     bufferPtr _ (self cCoerce: (interpreterProxy firstIndexableField: buffer)
  6846.                 to: 'int')
  6847.                 + startIndex - 1.    "adjust for zero-origin indexing"
  6848.     interpreterProxy failed ifFalse: [self cCode: 'asyncFileWriteStart(f, fPosition, bufferPtr, count)']! !
  6849.  
  6850. !AsynchFilePlugin class methodsFor: 'translation' stamp: 'ar 5/11/2000 22:21'!
  6851. headerFile
  6852. ^'/* Header file for AsynchFile plugin */
  6853. /* module initialization/shutdown */
  6854. int asyncFileInit(void);
  6855. int asyncFileShutdown(void);
  6856.  
  6857. /*** Experimental Asynchronous File I/O ***/
  6858. typedef struct {
  6859.     int            sessionID;
  6860.     void        *state;
  6861. } AsyncFile;
  6862.  
  6863. int asyncFileClose(AsyncFile *f);
  6864. int asyncFileOpen(AsyncFile *f, int fileNamePtr, int fileNameSize, int writeFlag, int semaIndex);
  6865. int asyncFileRecordSize();
  6866. int asyncFileReadResult(AsyncFile *f, int bufferPtr, int bufferSize);
  6867. int asyncFileReadStart(AsyncFile *f, int fPosition, int count);
  6868. int asyncFileWriteResult(AsyncFile *f);
  6869. int asyncFileWriteStart(AsyncFile *f, int fPosition, int bufferPtr, int bufferSize);
  6870. '! !
  6871.  
  6872. !AtomMorph methodsFor: 'as yet unclassified' stamp: 'jm 8/10/1998 17:40'!
  6873. bounceIn: aRect
  6874.     "Move this atom one step along its velocity vector and make it bounce if it goes outside the given rectangle. Return true if it is bounced."
  6875.  
  6876.     | p vx vy px py bounced |
  6877.     p _ self position.
  6878.     vx _ velocity x.        vy _ velocity y.
  6879.     px _ p x + vx.        py _ p y + vy.
  6880.     bounced _ false.
  6881.     px > aRect right ifTrue: [
  6882.         px _ aRect right - (px - aRect right).
  6883.         vx _ velocity x negated.
  6884.         bounced _ true].
  6885.     py > aRect bottom ifTrue: [
  6886.         py _  aRect bottom - (py - aRect bottom).
  6887.         vy _ velocity y negated.
  6888.         bounced _ true].
  6889.     px < aRect left ifTrue: [
  6890.         px _ aRect left - (px - aRect left).
  6891.         vx _ velocity x negated.
  6892.         bounced _ true].
  6893.     py < aRect top ifTrue: [
  6894.         py _  aRect top - (py - aRect top).
  6895.         vy _ velocity y negated.
  6896.         bounced _ true].
  6897.     self position: px @ py.
  6898.     bounced ifTrue: [self velocity: vx @ vy].
  6899.     ^ bounced
  6900. ! !
  6901.  
  6902. a stream on Text's which keeps track of the last attribute put; new characters are added with those attributes.
  6903.  
  6904. instance vars:
  6905.  
  6906.     characters - a WriteStream of the characters in the stream
  6907.     attributeRuns - a RunArray with the attributes for the stream
  6908.     currentAttributes - the attributes to be used for new text
  6909.     attributesChanged - whether the attributes have changed since the last addition!
  6910. !AttributedTextStream methodsFor: 'retrieving the text' stamp: 'ls 6/27/1998 15:04'!
  6911. contents
  6912.     | ans |
  6913.     ans _ Text new: characters size.
  6914.     ans setString: characters contents  setRuns: attributeRuns.   "this is declared private, but it's exactly what I need, and it's declared as exactly what I want it to do...."
  6915.     ^ans! !
  6916.  
  6917. !AttributedTextStream methodsFor: 'stream protocol' stamp: 'ls 6/27/1998 14:59'!
  6918. nextPut: aChar
  6919.     attributesChanged 
  6920.         ifTrue: [ 
  6921.             attributeRuns addLast: currentAttributes.
  6922.             attributesChanged _ false ]
  6923.         ifFalse: [
  6924.             attributeRuns  repeatLastIfEmpty: [ OrderedCollection new ] ].
  6925.     characters nextPut: aChar! !
  6926.  
  6927. !AttributedTextStream methodsFor: 'stream protocol' stamp: 'ls 6/27/1998 15:02'!
  6928. nextPutAll: aString
  6929.     "add an entire string with the same attributes"
  6930.     attributesChanged 
  6931.         ifTrue: [ attributeRuns addLast: currentAttributes times: aString size.
  6932.             attributesChanged _ false. ]
  6933.         ifFalse: [ attributeRuns repeatLast: aString size  ifEmpty: [ OrderedCollection new ] ].
  6934.     characters nextPutAll: aString.! !
  6935.  
  6936. !AttributedTextStream methodsFor: 'access' stamp: 'ls 6/27/1998 15:09'!
  6937. currentAttributes
  6938.     "return the current attributes"
  6939.     ^currentAttributes! !
  6940.  
  6941. !AttributedTextStream methodsFor: 'access' stamp: 'ls 7/28/1998 02:08'!
  6942. currentAttributes: newAttributes
  6943.     "set the current attributes"
  6944.     attributesChanged _ currentAttributes ~= newAttributes.
  6945.     currentAttributes _ newAttributes.
  6946. ! !
  6947.  
  6948. !AttributedTextStream methodsFor: 'access' stamp: 'ls 9/10/1998 03:36'!
  6949. size
  6950.     "number of characters in the stream so far"
  6951.     ^characters size! !
  6952.  
  6953. !AttributedTextStream methodsFor: 'private-initialization' stamp: 'ls 6/27/1998 15:08'!
  6954. initialize
  6955.     characters _ WriteStream on: String new.
  6956.     currentAttributes _ OrderedCollection new.
  6957.     attributesChanged _ true.
  6958.     attributeRuns _ RunArray new.
  6959.     ! !
  6960.  
  6961. !AttributedTextStream class methodsFor: 'instance creation' stamp: 'ls 6/27/1998 15:07'!
  6962. new
  6963.     ^super basicNew initialize! !
  6964.  
  6965. !AuthorizedSwikiAction methodsFor: 'URL processing' stamp: 'tk 9/21/1998 08:23'!
  6966. authorizer
  6967.     "*** Do not use this method to add or delete users!!  The change will not be recorded on the disk!!  Instead call mapName:password:to: in this class.***"
  6968.     ^authorizer! !
  6969.  
  6970. !AuthorizedSwikiAction methodsFor: 'URL processing' stamp: 'tk 7/6/1998 07:31'!
  6971. checkAuthorization: request
  6972.     ^ authorizer ifNotNil: [authorizer user: request userID].
  6973. ! !
  6974.  
  6975. !AuthorizedSwikiAction methodsFor: 'URL processing' stamp: 'mjg 8/31/1998
  6976. 15:32'!
  6977. process: request
  6978.     self checkAuthorization: request.
  6979.     ^(super process: request).! !
  6980.  
  6981. !AuthorizedSwikiAction methodsFor: 'URL processing' stamp: 'tk 9/13/1998 20:45'!
  6982. processSpecial: request
  6983.     "Let SwikiAction process this with no authorization check."
  6984.  
  6985.     ^(super process: request).! !
  6986.  
  6987. !AuthorizedSwikiAction methodsFor: 'URL processing' stamp: 'tk 6/22/1998 14:15'!
  6988. restore: nameOfSwiki
  6989.     "Read all files in the directory 'nameOfSwiki'.  Reconstruct the url map."
  6990.  
  6991.     | fName |
  6992.     super restore: nameOfSwiki.
  6993.     fName _ ServerAction serverDirectory, name, (ServerAction pathSeparator), 
  6994.                 'authorizer'.
  6995.     (FileDirectory new fileExists: fName) ifTrue: [
  6996.         authorizer _ (FileStream oldFileNamed: fName) fileInObjectAndCode].
  6997. ! !
  6998.  
  6999. Allows anyone to read the pages of this Swiki, but only authorized users can edit or change pages.  Can have multiple users, each with a different password.  Each can modify the whole Swiki area.
  7000.  
  7001. To restart an existing Authorized Swiki:
  7002.  
  7003.     AuthorizedWriteSwiki new restore: 'SWSecure'.
  7004.  
  7005. The front page URL is:  http://serverMachine:80/SWSecure.1
  7006.  
  7007. To make a completely new one:
  7008.     | a s |
  7009.     a := Authorizer new.
  7010.     a realm: 'SwikiArea'.
  7011.     a mapName: 'viki' password: 'hard2guess' to: 'viki'.
  7012.     AuthorizedWriteSwiki setUp: 'SWSecure'.
  7013.     s := AuthorizedWriteSwiki new restore: 'SWSecure'.
  7014.     s authorizer: a.
  7015. !
  7016. !AuthorizedWriteSwiki methodsFor: 'as yet unclassified' stamp: 'tk 9/13/1998 20:59'!
  7017. process: request
  7018.     "Only demand authorization of name and password when requesting the edit page, requesting the append page, receiving an edit, or receiving an append."
  7019.  
  7020.     | command coreRef |
  7021.     request fields ifNotNil: ["Are there input fields?"
  7022.         coreRef _ request message size < 2
  7023.             ifTrue: ['1']
  7024.             ifFalse: [request message at: 2].
  7025.         coreRef = 'searchresult' ifFalse: ["Must be text for an edit!!"
  7026.             self checkAuthorization: request]].
  7027.     request message size > 2 ifTrue:
  7028.             ["SearchResult, All, Versions, or Edit"
  7029.             command _ request message at: 3.
  7030.             command = 'edit' ifTrue:
  7031.                     [self checkAuthorization: request].
  7032.             command = 'insert' ifTrue:
  7033.                     [self checkAuthorization: request]].
  7034.  
  7035.     ^(super processSpecial: request).        "all the way up to SwikiAction"! !
  7036.  
  7037. B3DAcceleratorPlugin translate!
  7038. !B3DAcceleratorPlugin methodsFor: 'initialize-release' stamp: 'ar 5/26/2000 17:23'!
  7039. initialiseModule
  7040.     self export: true.
  7041.     ^self b3dxInitialize! !
  7042.  
  7043. !B3DAcceleratorPlugin methodsFor: 'initialize-release' stamp: 'ar 5/26/2000 17:23'!
  7044. shutdownModule
  7045.     self export: true.
  7046.     ^self b3dxShutdown! !
  7047.  
  7048. !B3DAcceleratorPlugin methodsFor: 'primitives-display' stamp: 'ar 5/28/2000 01:54'!
  7049. primitiveBltFromDisplay
  7050.     | result extent srcOrigin dstOrigin extentX extentY sourceX sourceY destX destY formHandle displayHandle |
  7051.     self export: true.
  7052.     interpreterProxy methodArgumentCount = 5
  7053.         ifFalse:[^interpreterProxy primitiveFail].
  7054.     extent _ interpreterProxy stackObjectValue: 0.
  7055.     srcOrigin _ interpreterProxy stackObjectValue: 1.
  7056.     dstOrigin _ interpreterProxy stackObjectValue: 2.
  7057.     formHandle _ interpreterProxy stackIntegerValue: 3.
  7058.     displayHandle _ interpreterProxy stackIntegerValue: 4.
  7059.     interpreterProxy failed ifTrue:[^nil].
  7060.     ((interpreterProxy isPointers: extent) and:[(interpreterProxy slotSizeOf: extent) = 2])
  7061.         ifFalse:[^interpreterProxy primitiveFail].
  7062.     ((interpreterProxy isPointers: srcOrigin) and:[(interpreterProxy slotSizeOf: srcOrigin) = 2])
  7063.         ifFalse:[^interpreterProxy primitiveFail].
  7064.     ((interpreterProxy isPointers: dstOrigin) and:[(interpreterProxy slotSizeOf: dstOrigin) = 2])
  7065.         ifFalse:[^interpreterProxy primitiveFail].
  7066.     extentX _ interpreterProxy fetchInteger: 0 ofObject: extent.
  7067.     extentY _ interpreterProxy fetchInteger: 1 ofObject: extent.
  7068.     sourceX _ interpreterProxy fetchInteger: 0 ofObject: srcOrigin.
  7069.     sourceY _ interpreterProxy fetchInteger: 1 ofObject: srcOrigin.
  7070.     destX _ interpreterProxy fetchInteger: 0 ofObject: dstOrigin.
  7071.     destY _ interpreterProxy fetchInteger: 1 ofObject: dstOrigin.
  7072.     interpreterProxy failed ifTrue:[^nil].
  7073.     result _ self cCode:'b3dxBltFromDisplay(displayHandle, formHandle, destX, destY, sourceX, sourceY, extentX, extentY)' inSmalltalk:[false].
  7074.     result ifFalse:[^interpreterProxy primitiveFail].
  7075.     interpreterProxy pop: 5. "pop args; return rcvr"! !
  7076.  
  7077. !B3DAcceleratorPlugin methodsFor: 'primitives-display' stamp: 'ar 5/28/2000 01:55'!
  7078. primitiveBltToDisplay
  7079.     | result extent srcOrigin dstOrigin extentX extentY sourceX sourceY destX destY formHandle displayHandle |
  7080.     self export: true.
  7081.     interpreterProxy methodArgumentCount = 5
  7082.         ifFalse:[^interpreterProxy primitiveFail].
  7083.     extent _ interpreterProxy stackObjectValue: 0.
  7084.     srcOrigin _ interpreterProxy stackObjectValue: 1.
  7085.     dstOrigin _ interpreterProxy stackObjectValue: 2.
  7086.     formHandle _ interpreterProxy stackIntegerValue: 3.
  7087.     displayHandle _ interpreterProxy stackIntegerValue: 4.
  7088.     interpreterProxy failed ifTrue:[^nil].
  7089.     ((interpreterProxy isPointers: extent) and:[(interpreterProxy slotSizeOf: extent) = 2])
  7090.         ifFalse:[^interpreterProxy primitiveFail].
  7091.     ((interpreterProxy isPointers: srcOrigin) and:[(interpreterProxy slotSizeOf: srcOrigin) = 2])
  7092.         ifFalse:[^interpreterProxy primitiveFail].
  7093.     ((interpreterProxy isPointers: dstOrigin) and:[(interpreterProxy slotSizeOf: dstOrigin) = 2])
  7094.         ifFalse:[^interpreterProxy primitiveFail].
  7095.     extentX _ interpreterProxy fetchInteger: 0 ofObject: extent.
  7096.     extentY _ interpreterProxy fetchInteger: 1 ofObject: extent.
  7097.     sourceX _ interpreterProxy fetchInteger: 0 ofObject: srcOrigin.
  7098.     sourceY _ interpreterProxy fetchInteger: 1 ofObject: srcOrigin.
  7099.     destX _ interpreterProxy fetchInteger: 0 ofObject: dstOrigin.
  7100.     destY _ interpreterProxy fetchInteger: 1 ofObject: dstOrigin.
  7101.     interpreterProxy failed ifTrue:[^nil].
  7102.     result _ self cCode:'b3dxBltToDisplay(displayHandle, formHandle, destX, destY, sourceX, sourceY, extentX, extentY)' inSmalltalk:[false].
  7103.     result ifFalse:[^interpreterProxy primitiveFail].
  7104.     interpreterProxy pop: 5. "pop args; return rcvr"! !
  7105.  
  7106. !B3DAcceleratorPlugin methodsFor: 'primitives-display' stamp: 'ar 5/28/2000 01:15'!
  7107. primitiveCreateDisplaySurface
  7108.     | h w d result |
  7109.     self export: true.
  7110.     interpreterProxy methodArgumentCount = 3
  7111.         ifFalse:[^interpreterProxy primitiveFail].
  7112.     h _ interpreterProxy stackIntegerValue: 0.
  7113.     w _ interpreterProxy stackIntegerValue: 1.
  7114.     d _ interpreterProxy stackIntegerValue: 2.
  7115.     interpreterProxy failed ifTrue:[^nil].
  7116.     result _ self cCode:'b3dxCreateDisplaySurface(w, h, d)' inSmalltalk:[-1].
  7117.     result = -1 ifTrue:[^interpreterProxy primitiveFail].
  7118.     interpreterProxy pop: 4. "args+rcvr"
  7119.     interpreterProxy pushInteger: result.! !
  7120.  
  7121. !B3DAcceleratorPlugin methodsFor: 'primitives-display' stamp: 'ar 5/28/2000 01:16'!
  7122. primitiveDestroyDisplaySurface
  7123.     | handle result |
  7124.     self export: true.
  7125.     interpreterProxy methodArgumentCount = 1
  7126.         ifFalse:[^interpreterProxy primitiveFail].
  7127.     handle _ interpreterProxy stackIntegerValue: 0.
  7128.     interpreterProxy failed ifTrue:[^nil].
  7129.     result _ self cCode:'b3dxDestroyDisplaySurface(handle)' inSmalltalk:[false].
  7130.     result ifFalse:[^interpreterProxy primitiveFail].
  7131.     interpreterProxy pop: 1. "pop arg; return rcvr"! !
  7132.  
  7133. !B3DAcceleratorPlugin methodsFor: 'primitives-display' stamp: 'ar 5/27/2000 21:36'!
  7134. primitiveDisplayGetColorMasks
  7135.     | handle result masks array |
  7136.     self export: true.
  7137.     self var: #masks declareC:'int masks[4]'.
  7138.     interpreterProxy methodArgumentCount = 2
  7139.         ifFalse:[^interpreterProxy primitiveFail].
  7140.     array _ interpreterProxy stackObjectValue: 0.
  7141.     handle _ interpreterProxy stackIntegerValue: 1.
  7142.     interpreterProxy failed ifTrue:[^nil].
  7143.     (interpreterProxy fetchClassOf: array) = interpreterProxy classArray
  7144.         ifFalse:[^interpreterProxy primitiveFail].
  7145.     (interpreterProxy slotSizeOf: array) = 4
  7146.         ifFalse:[^interpreterProxy primitiveFail].
  7147.     result _ self cCode:'b3dxDisplayColorMasks(handle, masks)' inSmalltalk:[false].
  7148.     result ifFalse:[^interpreterProxy primitiveFail].
  7149.     0 to: 3 do:[:i|
  7150.         interpreterProxy storePointer: i ofObject: array withValue:
  7151.             (interpreterProxy positive32BitIntegerFor: (masks at: i))].
  7152.     interpreterProxy pop: 2. "pop args return receiver"! !
  7153.  
  7154. !B3DAcceleratorPlugin methodsFor: 'primitives-display' stamp: 'ar 5/28/2000 01:16'!
  7155. primitiveFillDisplaySurface
  7156.     | h w result y x pv handle |
  7157.     self export: true.
  7158.     interpreterProxy methodArgumentCount = 6
  7159.         ifFalse:[^interpreterProxy primitiveFail].
  7160.     h _ interpreterProxy stackIntegerValue: 0.
  7161.     w _ interpreterProxy stackIntegerValue: 1.
  7162.     y _ interpreterProxy stackIntegerValue: 2.
  7163.     x _ interpreterProxy stackIntegerValue: 3.
  7164.     pv _ interpreterProxy positive32BitValueOf: (interpreterProxy stackValue: 4).
  7165.     handle _ interpreterProxy stackIntegerValue: 5.
  7166.     interpreterProxy failed ifTrue:[^nil].
  7167.     result _ self cCode:'b3dxFillDisplaySurface(handle, pv, x, y, w, h)' inSmalltalk:[false].
  7168.     result ifFalse:[^interpreterProxy primitiveFail].
  7169.     interpreterProxy pop: 6. "pop args; return rcvr"! !
  7170.  
  7171. !B3DAcceleratorPlugin methodsFor: 'primitives-display' stamp: 'ar 5/28/2000 01:17'!
  7172. primitiveFinishDisplaySurface
  7173.     | handle result |
  7174.     self export: true.
  7175.     interpreterProxy methodArgumentCount = 1
  7176.         ifFalse:[^interpreterProxy primitiveFail].
  7177.     handle _ interpreterProxy stackIntegerValue: 0.
  7178.     interpreterProxy failed ifTrue:[^nil].
  7179.     result _ self cCode:'b3dxFinishDisplaySurface(handle)' inSmalltalk:[false].
  7180.     result ifFalse:[^interpreterProxy primitiveFail].
  7181.     interpreterProxy pop: 1. "pop arg; return rcvr"! !
  7182.  
  7183. !B3DAcceleratorPlugin methodsFor: 'primitives-display' stamp: 'ar 5/28/2000 01:17'!
  7184. primitiveFlushDisplaySurface
  7185.     | handle result |
  7186.     self export: true.
  7187.     interpreterProxy methodArgumentCount = 1
  7188.         ifFalse:[^interpreterProxy primitiveFail].
  7189.     handle _ interpreterProxy stackIntegerValue: 0.
  7190.     interpreterProxy failed ifTrue:[^nil].
  7191.     result _ self cCode:'b3dxFlushDisplaySurface(handle)' inSmalltalk:[false].
  7192.     result ifFalse:[^interpreterProxy primitiveFail].
  7193.     interpreterProxy pop: 1. "pop arg; return rcvr"! !
  7194.  
  7195. !B3DAcceleratorPlugin methodsFor: 'primitives-display' stamp: 'ar 5/27/2000 21:37'!
  7196. primitiveSupportsDisplayDepth
  7197.     | result depth |
  7198.     self export: true.
  7199.     interpreterProxy methodArgumentCount = 1
  7200.         ifFalse:[^interpreterProxy primitiveFail].
  7201.     depth _ interpreterProxy stackIntegerValue: 0.
  7202.     interpreterProxy failed ifTrue:[^nil].
  7203.     result _ self b3dxSupportsDisplayDepth: depth.
  7204.     interpreterProxy pop: 1.
  7205.     interpreterProxy pushBool: result.! !
  7206.  
  7207. !B3DAcceleratorPlugin methodsFor: 'primitives-textures' stamp: 'ar 5/28/2000 01:17'!
  7208. primitiveAllocateTexture
  7209.     | h w d result |
  7210.     self export: true.
  7211.     interpreterProxy methodArgumentCount = 3
  7212.         ifFalse:[^interpreterProxy primitiveFail].
  7213.     h _ interpreterProxy stackIntegerValue: 0.
  7214.     w _ interpreterProxy stackIntegerValue: 1.
  7215.     d _ interpreterProxy stackIntegerValue: 2.
  7216.     interpreterProxy failed ifTrue:[^nil].
  7217.     result _ self cCode:'b3dxAllocateTexture(w, h, d)' inSmalltalk:[-1].
  7218.     result = -1 ifTrue:[^interpreterProxy primitiveFail].
  7219.     interpreterProxy pop: 4. "args+rcvr"
  7220.     interpreterProxy pushInteger: result.! !
  7221.  
  7222. !B3DAcceleratorPlugin methodsFor: 'primitives-textures' stamp: 'ar 5/28/2000 01:18'!
  7223. primitiveDestroyTexture
  7224.     | handle result |
  7225.     self export: true.
  7226.     interpreterProxy methodArgumentCount = 1
  7227.         ifFalse:[^interpreterProxy primitiveFail].
  7228.     handle _ interpreterProxy stackIntegerValue: 0.
  7229.     interpreterProxy failed ifTrue:[^nil].
  7230.     result _ self cCode:'b3dxDestroyTexture(handle)' inSmalltalk:[false].
  7231.     result ifFalse:[^interpreterProxy primitiveFail].
  7232.     interpreterProxy pop: 1. "pop arg; return rcvr"! !
  7233.  
  7234. !B3DAcceleratorPlugin methodsFor: 'primitives-textures' stamp: 'ar 5/27/2000 21:37'!
  7235. primitiveTextureDepth
  7236.     | handle result |
  7237.     self export: true.
  7238.     interpreterProxy methodArgumentCount = 1
  7239.         ifFalse:[^interpreterProxy primitiveFail].
  7240.     handle _ interpreterProxy stackIntegerValue: 0.
  7241.     interpreterProxy failed ifTrue:[^nil].
  7242.     result _ self cCode:'b3dxActualTextureDepth(handle)' inSmalltalk:[-1].
  7243.     result < 0 ifTrue:[^interpreterProxy primitiveFail].
  7244.     interpreterProxy pop: 2.
  7245.     interpreterProxy pushInteger: result.! !
  7246.  
  7247. !B3DAcceleratorPlugin methodsFor: 'primitives-textures' stamp: 'ar 5/27/2000 21:37'!
  7248. primitiveTextureGetColorMasks
  7249.     | handle result masks array |
  7250.     self export: true.
  7251.     self var: #masks declareC:'int masks[4]'.
  7252.     interpreterProxy methodArgumentCount = 2
  7253.         ifFalse:[^interpreterProxy primitiveFail].
  7254.     array _ interpreterProxy stackObjectValue: 0.
  7255.     handle _ interpreterProxy stackIntegerValue: 1.
  7256.     interpreterProxy failed ifTrue:[^nil].
  7257.     (interpreterProxy fetchClassOf: array) = interpreterProxy classArray
  7258.         ifFalse:[^interpreterProxy primitiveFail].
  7259.     (interpreterProxy slotSizeOf: array) = 4
  7260.         ifFalse:[^interpreterProxy primitiveFail].
  7261.     result _ self cCode:'b3dxTextureColorMasks(handle, masks)' inSmalltalk:[false].
  7262.     result ifFalse:[^interpreterProxy primitiveFail].
  7263.     0 to: 3 do:[:i|
  7264.         interpreterProxy storePointer: i ofObject: array withValue:
  7265.             (interpreterProxy positive32BitIntegerFor: (masks at: i))].
  7266.     interpreterProxy pop: 2. "pop args return receiver"! !
  7267.  
  7268. !B3DAcceleratorPlugin methodsFor: 'primitives-textures' stamp: 'ar 5/28/2000 01:18'!
  7269. primitiveTextureHeight
  7270.     | handle result |
  7271.     self export: true.
  7272.     interpreterProxy methodArgumentCount = 1
  7273.         ifFalse:[^interpreterProxy primitiveFail].
  7274.     handle _ interpreterProxy stackIntegerValue: 0.
  7275.     interpreterProxy failed ifTrue:[^nil].
  7276.     result _ self cCode:'b3dxActualTextureHeight(handle)' inSmalltalk:[-1].
  7277.     result < 0 ifTrue:[^interpreterProxy primitiveFail].
  7278.     interpreterProxy pop: 2.
  7279.     interpreterProxy pushInteger: result.! !
  7280.  
  7281. !B3DAcceleratorPlugin methodsFor: 'primitives-textures' stamp: 'ar 5/28/2000 01:19'!
  7282. primitiveTextureWidth
  7283.     | handle result |
  7284.     self export: true.
  7285.     interpreterProxy methodArgumentCount = 1
  7286.         ifFalse:[^interpreterProxy primitiveFail].
  7287.     handle _ interpreterProxy stackIntegerValue: 0.
  7288.     interpreterProxy failed ifTrue:[^nil].
  7289.     result _ self cCode:'b3dxActualTextureWidth(handle)' inSmalltalk:[-1].
  7290.     result < 0 ifTrue:[^interpreterProxy primitiveFail].
  7291.     interpreterProxy pop: 2.
  7292.     interpreterProxy pushInteger: result.! !
  7293.  
  7294. !B3DAcceleratorPlugin methodsFor: 'primitives-forms' stamp: 'ar 5/28/2000 01:19'!
  7295. primitiveAllocateForm
  7296.     | h w d result |
  7297.     self export: true.
  7298.     interpreterProxy methodArgumentCount = 3
  7299.         ifFalse:[^interpreterProxy primitiveFail].
  7300.     h _ interpreterProxy stackIntegerValue: 0.
  7301.     w _ interpreterProxy stackIntegerValue: 1.
  7302.     d _ interpreterProxy stackIntegerValue: 2.
  7303.     interpreterProxy failed ifTrue:[^nil].
  7304.     result _ self cCode:'b3dxAllocateForm(w, h, d)' inSmalltalk:[-1].
  7305.     result = -1 ifTrue:[^interpreterProxy primitiveFail].
  7306.     interpreterProxy pop: 4. "args+rcvr"
  7307.     interpreterProxy pushInteger: result.! !
  7308.  
  7309. !B3DAcceleratorPlugin methodsFor: 'primitives-forms' stamp: 'ar 5/28/2000 01:19'!
  7310. primitiveDestroyForm
  7311.     | handle result |
  7312.     self export: true.
  7313.     interpreterProxy methodArgumentCount = 1
  7314.         ifFalse:[^interpreterProxy primitiveFail].
  7315.     handle _ interpreterProxy stackIntegerValue: 0.
  7316.     interpreterProxy failed ifTrue:[^nil].
  7317.     result _ self cCode:'b3dxDestroyForm(handle)' inSmalltalk:[false].
  7318.     result ifFalse:[^interpreterProxy primitiveFail].
  7319.     interpreterProxy pop: 1. "pop arg; return rcvr"! !
  7320.  
  7321. !B3DAcceleratorPlugin methodsFor: 'primitives-forms' stamp: 'ar 5/27/2000 21:38'!
  7322. primitiveFormGetColorMasks
  7323.     | handle result masks array |
  7324.     self export: true.
  7325.     self var: #masks declareC:'int masks[4]'.
  7326.     interpreterProxy methodArgumentCount = 2
  7327.         ifFalse:[^interpreterProxy primitiveFail].
  7328.     array _ interpreterProxy stackObjectValue: 0.
  7329.     handle _ interpreterProxy stackIntegerValue: 1.
  7330.     interpreterProxy failed ifTrue:[^nil].
  7331.     (interpreterProxy fetchClassOf: array) = interpreterProxy classArray
  7332.         ifFalse:[^interpreterProxy primitiveFail].
  7333.     (interpreterProxy slotSizeOf: array) = 4
  7334.         ifFalse:[^interpreterProxy primitiveFail].
  7335.     result _ self cCode:'b3dxFormColorMasks(handle, masks)' inSmalltalk:[false].
  7336.     result ifFalse:[^interpreterProxy primitiveFail].
  7337.     0 to: 3 do:[:i|
  7338.         interpreterProxy storePointer: i ofObject: array withValue:
  7339.             (interpreterProxy positive32BitIntegerFor: (masks at: i))].
  7340.     interpreterProxy pop: 2. "pop args return receiver"! !
  7341.  
  7342. !B3DAcceleratorPlugin methodsFor: 'primitives-rasterizer' stamp: 'ar 5/28/2000 01:19'!
  7343. primitiveClearDepthBuffer
  7344.     | result |
  7345.     self export: true.
  7346.     interpreterProxy methodArgumentCount = 0
  7347.         ifFalse:[^interpreterProxy primitiveFail].
  7348.     result _ self cCode:'b3dxClearDepthBuffer()'.
  7349.     result ifFalse:[^interpreterProxy primitiveFail].
  7350.     interpreterProxy pop: 4. "pop args; return rcvr"! !
  7351.  
  7352. !B3DAcceleratorPlugin methodsFor: 'primitives-rasterizer' stamp: 'ar 5/28/2000 01:20'!
  7353. primitiveProcessVertexBuffer
  7354.     | idxCount vtxCount vtxArray idxArray texHandle primType result |
  7355.     self export: true.
  7356.     self var: #idxArray type: 'int *'.
  7357.     self var: #vtxArray type: 'float *'.
  7358.     interpreterProxy methodArgumentCount = 6
  7359.         ifFalse:[^interpreterProxy primitiveFail].
  7360.     idxCount _ interpreterProxy stackIntegerValue: 0.
  7361.     vtxCount _ interpreterProxy stackIntegerValue: 2.
  7362.     texHandle _ interpreterProxy stackIntegerValue: 4.
  7363.     primType _ interpreterProxy stackIntegerValue: 5.
  7364.     interpreterProxy failed ifTrue:[^nil].
  7365.     vtxArray _ self stackPrimitiveVertexArray: 3 ofSize: vtxCount.
  7366.     idxArray _ self stackPrimitiveIndexArray: 1 ofSize: idxCount validate: true forVertexSize: vtxCount.
  7367.     (vtxArray == nil or:[idxArray == nil 
  7368.         or:[primType < 1 or:[primType > PrimTypeMax 
  7369.             or:[interpreterProxy failed]]]])
  7370.                 ifTrue:[^interpreterProxy primitiveFail].
  7371.  
  7372.     result _ self cCode:'b3dxRasterizeVertexBuffer(primType, texHandle, vtxArray, vtxCount, idxArray, idxCount)' inSmalltalk:[false].
  7373.     result ifFalse:[^interpreterProxy primitiveFail].
  7374.     interpreterProxy pop: 6. "pop args; return rcvr"! !
  7375.  
  7376. !B3DAcceleratorPlugin methodsFor: 'primitives-rasterizer' stamp: 'ar 5/26/2000 17:24'!
  7377. primitiveRasterizerVersion
  7378.     self export: true.
  7379.     interpreterProxy methodArgumentCount = 0
  7380.         ifFalse:[^interpreterProxy primitiveFail].
  7381.     interpreterProxy pop: 1.
  7382.     interpreterProxy pushInteger: 1.! !
  7383.  
  7384. !B3DAcceleratorPlugin methodsFor: 'primitives-rasterizer' stamp: 'ar 5/28/2000 01:20'!
  7385. primitiveSetViewport
  7386.     | h w y x result |
  7387.     self export: true.
  7388.     interpreterProxy methodArgumentCount = 4
  7389.         ifFalse:[^interpreterProxy primitiveFail].
  7390.     h _ interpreterProxy stackIntegerValue: 0.
  7391.     w _ interpreterProxy stackIntegerValue: 1.
  7392.     y _ interpreterProxy stackIntegerValue: 2.
  7393.     x _ interpreterProxy stackIntegerValue: 3.
  7394.     interpreterProxy failed ifTrue:[^nil].
  7395.     result _ self cCode:'b3dxSetViewport(x, y, w, h)'.
  7396.     result ifFalse:[^interpreterProxy primitiveFail].
  7397.     interpreterProxy pop: 4. "pop args; return rcvr"! !
  7398.  
  7399. !B3DAcceleratorPlugin methodsFor: 'primitive support' stamp: 'ar 5/26/2000 12:37'!
  7400. stackPrimitiveIndexArray: stackIndex ofSize: nItems validate: aBool forVertexSize: maxIndex
  7401.     "Load a primitive index array from the interpreter stack.
  7402.     If aBool is true then check that all the indexes are in the range (1,maxIndex).
  7403.     Return a pointer to the index data if successful, nil otherwise."
  7404.     | oop oopSize idxPtr index |
  7405.     self inline: false.
  7406.     self returnTypeC:'void*'.
  7407.     self var: #idxPtr declareC:'int *idxPtr'.
  7408.  
  7409.     oop _ interpreterProxy stackObjectValue: stackIndex.
  7410.     oop = nil ifTrue:[^nil].
  7411.     (interpreterProxy isWords: oop) ifFalse:[^nil].
  7412.      oopSize _ interpreterProxy slotSizeOf: oop.
  7413.     oopSize < nItems ifTrue:[^nil].
  7414.     idxPtr _ self cCoerce: (interpreterProxy firstIndexableField: oop) to:'int *'.
  7415.     aBool ifTrue:[
  7416.         0 to: nItems-1 do:[:i|
  7417.             index _ idxPtr at: i.
  7418.             (index < 0 or:[index > maxIndex]) ifTrue:[^nil]]].
  7419.     ^idxPtr! !
  7420.  
  7421. !B3DAcceleratorPlugin methodsFor: 'primitive support' stamp: 'ar 5/26/2000 12:38'!
  7422. stackPrimitiveVertex: index
  7423.     "Load a primitive vertex from the interpreter stack.
  7424.     Return a pointer to the vertex data if successful, nil otherwise."
  7425.     | oop |
  7426.     self inline: false.
  7427.     self returnTypeC:'void*'.
  7428.     oop _ interpreterProxy stackObjectValue: index.
  7429.     oop = nil ifTrue:[^nil].
  7430.     ((interpreterProxy isWords: oop) and:[(interpreterProxy slotSizeOf: oop) = PrimVertexSize])
  7431.         ifTrue:[^interpreterProxy firstIndexableField: oop].
  7432.     ^nil! !
  7433.  
  7434. !B3DAcceleratorPlugin methodsFor: 'primitive support' stamp: 'ar 5/26/2000 12:38'!
  7435. stackPrimitiveVertexArray: index ofSize: nItems
  7436.     "Load a primitive vertex array from the interpreter stack.
  7437.     Return a pointer to the vertex data if successful, nil otherwise."
  7438.     | oop oopSize |
  7439.     self inline: false.
  7440.     self returnTypeC:'void*'.
  7441.     oop _ interpreterProxy stackObjectValue: index.
  7442.     oop = nil ifTrue:[^nil].
  7443.     (interpreterProxy isWords: oop) ifTrue:[
  7444.          oopSize _ interpreterProxy slotSizeOf: oop.
  7445.         (oopSize >= nItems * PrimVertexSize and:[oopSize \\ PrimVertexSize = 0])
  7446.             ifTrue:[^interpreterProxy firstIndexableField: oop]].
  7447.     ^nil! !
  7448.  
  7449. !B3DAcceleratorPlugin class methodsFor: 'translation' stamp: 'ar 5/28/2000 01:50'!
  7450. headerFile
  7451. ^'/* Header file for 3D accelerator plugin */
  7452.  
  7453. /* module initialization support */
  7454. int b3dxInitialize(void); /* return true on success, false on error */
  7455. int b3dxShutdown(void); /* return true on success, false on error */
  7456.  
  7457. /* Display support primitives */
  7458. int b3dxCreateDisplaySurface(int w, int h, int d); /* return handle or -1 on error */
  7459. int b3dxDestroyDisplaySurface(int handle); /* return true on success, false on error */
  7460. int b3dxDisplayColorMasks(int handle, int masks[4]); /* return true on success, false on error */
  7461. int b3dxSupportsDisplayDepth(int depth); /* return true or false */
  7462. int b3dxFlushDisplaySurface(int handle); /* return true on success, false on error */
  7463. int b3dxFinishDisplaySurface(int handle); /* return true on success, false on error */
  7464.  
  7465. /* optional accelerated blt primitives */
  7466. int b3dxFillDisplaySurface(int handle, int pv, int x, int y, int w, int h); /* return true on success, false on error */
  7467. int b3dxBltToDisplay(int displayHandle, int formHandle, int dstX, int dstY, int srcX, int srcY, int w, int h); /* return true on success, false on error */
  7468. int b3dxBltFromDisplay(int displayHandle, int formHandle, int dstX, int dstY, int srcX, int srcY, int w, int h); /* return true on success, false on error */
  7469.  
  7470. /* Texture support primitives */
  7471. int b3dxAllocateTexture(int w, int h, int d); /* return handle or -1 on error */
  7472. int b3dxDestroyTexture(int handle); /* return true on success, false on error */
  7473. int b3dxActualTextureDepth(int handle); /* return depth or <0 on error */
  7474. int b3dxActualTextureWidth(int handle); /* return width or <0 on error */
  7475. int b3dxActualTextureHeight(int handle); /* return height or <0 on error */
  7476. int b3dxTextureColorMasks(int handle, int masks[4]);  /* return true on success, false on error */
  7477.  
  7478. /* Form support primitives */
  7479. int b3dxAllocateForm(int w, int h, int d); /* return handle or -1 on error */
  7480. int b3dxDestroyForm(int handle); /* return true on success, false on error */
  7481. int b3dxFormColorMasks(int handle, int masks[4]);  /* return true on success, false on error */
  7482.  
  7483. /* Rasterizer support primitives */
  7484. int b3dxSetViewport(int x, int y, int w, int h); /* return true on success, false on error */
  7485. int b3dxClearDepthBuffer(void); /* return true on success, false on error */
  7486. int b3dxRasterizeVertexBuffer(int primType, int texHandle, float *vtxArray, int vtxSize, int *idxArray, int idxSize); /* return true on success, false on error */
  7487.  
  7488. '.! !
  7489.  
  7490. !B3DAcceleratorPlugin class methodsFor: 'translation' stamp: 'ar 5/26/2000 17:25'!
  7491. moduleName
  7492.     ^'Squeak3DX'! !
  7493.  
  7494. !B3DActiveEdgeTable methodsFor: 'initialize' stamp: 'ar 4/4/1999 20:55'!
  7495. initialize
  7496.     array _ Array new: 100.
  7497.     start _ 0.
  7498.     stop _ 0.! !
  7499.  
  7500. !B3DActiveEdgeTable methodsFor: 'accessing' stamp: 'ar 4/6/1999 02:21'!
  7501. at: index
  7502.     ^array at: index! !
  7503.  
  7504. !B3DActiveEdgeTable methodsFor: 'accessing' stamp: 'ar 4/18/1999 05:48'!
  7505. first
  7506.     ^array at: 1! !
  7507.  
  7508. !B3DActiveEdgeTable methodsFor: 'accessing' stamp: 'ar 4/6/1999 23:20'!
  7509. indexOf: anEdge
  7510.     1 to: stop do:[:i| (array at: i) = anEdge ifTrue:[^i]].
  7511.     ^0! !
  7512.  
  7513. !B3DActiveEdgeTable methodsFor: 'accessing' stamp: 'ar 4/18/1999 05:48'!
  7514. last
  7515.     ^array at: stop! !
  7516.  
  7517. !B3DActiveEdgeTable methodsFor: 'accessing' stamp: 'ar 4/3/1999 05:28'!
  7518. size
  7519.     ^stop! !
  7520.  
  7521. !B3DActiveEdgeTable methodsFor: 'accessing' stamp: 'ar 4/6/1999 03:51'!
  7522. xValues
  7523.     ^(array copyFrom: 1 to: stop) collect:[:e| e xValue]! !
  7524.  
  7525. !B3DActiveEdgeTable methodsFor: 'streaming' stamp: 'ar 4/3/1999 05:28'!
  7526. atEnd
  7527.     ^start >= stop! !
  7528.  
  7529. !B3DActiveEdgeTable methodsFor: 'streaming' stamp: 'ar 4/3/1999 05:28'!
  7530. next
  7531.     "Return the next entry from the AET and advance start"
  7532.     ^array at: (start _ start + 1)! !
  7533.  
  7534. !B3DActiveEdgeTable methodsFor: 'streaming' stamp: 'ar 4/5/1999 23:24'!
  7535. peek
  7536.     "Peek the next entry from the AET"
  7537.     ^array at: (start + 1)! !
  7538.  
  7539. !B3DActiveEdgeTable methodsFor: 'streaming' stamp: 'ar 4/3/1999 05:28'!
  7540. reset
  7541.     start _ 0.! !
  7542.  
  7543. !B3DActiveEdgeTable methodsFor: 'merging' stamp: 'ar 4/4/1999 21:52'!
  7544. mergeEdgesFrom: inputList
  7545.     "Merge all the edges from the given input list in the AET"
  7546.     | srcIndex dstIndex outIndex srcEdge dstEdge |
  7547.     srcIndex _ inputList size.
  7548.     srcIndex = 0 ifTrue:[^self].
  7549.     dstIndex _ stop.
  7550.     "Make room for adding the stuff"
  7551.     [stop + srcIndex > array size] whileTrue:[self grow].
  7552.     "Adjust size"
  7553.     stop _ stop + srcIndex.
  7554.     "If the receiver is empty, simply copy the stuff"
  7555.     dstIndex = 0 ifTrue:[
  7556.         1 to: srcIndex do:[:i| array at: i put: (inputList at: i)].
  7557.         ^self].
  7558.     "Merge inputList by walking backwards through the AET and checking each edge."
  7559.     outIndex _ dstIndex+srcIndex.
  7560.     srcEdge _ inputList at: srcIndex.
  7561.     dstEdge _ array at: dstIndex.
  7562.     [true] whileTrue:[
  7563.         srcEdge xValue >= dstEdge xValue ifTrue:[
  7564.             "Insert srcEdge"
  7565.             array at: outIndex put: srcEdge.
  7566.             srcIndex _ srcIndex - 1.
  7567.             srcIndex = 0 ifTrue:[^self].
  7568.             srcEdge _ inputList at: srcIndex.
  7569.         ] ifFalse:[
  7570.             "Insert dstEdge"
  7571.             array at: outIndex put: dstEdge.
  7572.             dstIndex _ dstIndex - 1.
  7573.             dstIndex = 0 ifTrue:[
  7574.                 1 to: srcIndex do:[:i| array at: i put: (inputList at: i)].
  7575.                 ^self].
  7576.             dstEdge _ array at: dstIndex.
  7577.         ].
  7578.         outIndex _ outIndex-1.
  7579.     ].! !
  7580.  
  7581. !B3DActiveEdgeTable methodsFor: 'removing' stamp: 'ar 4/5/1999 03:15'!
  7582. removeFirst
  7583.     stop _ stop - 1.
  7584.     array replaceFrom: start to: stop with: array startingAt: start+1.
  7585.     start _ start - 1.
  7586.     array at: stop+1 put: nil.! !
  7587.  
  7588. !B3DActiveEdgeTable methodsFor: 'sorting' stamp: 'ar 4/3/1999 05:27'!
  7589. resortFirst
  7590.     "Resort the first entry in the active edge table"
  7591.     | edge xValue leftEdge newIndex |
  7592.     start = 1 ifTrue:[^self]. "Nothing to do"
  7593.     "Fetch the edge to test."
  7594.     edge _ array at: start.
  7595.     xValue _ edge xValue.
  7596.     "Fetch the next edge left to it."
  7597.     leftEdge _ array at: start-1.
  7598.     leftEdge xValue <= xValue ifTrue:[^self]. "Okay."
  7599.     "Move the edge left to its correct insertion point."
  7600.     newIndex _ start.
  7601.     [newIndex > 1 and:[(leftEdge _ array at: newIndex-1) xValue > xValue]]
  7602.         whileTrue:[    array at: newIndex put: leftEdge.
  7603.                     newIndex _ newIndex - 1].
  7604.     array at: newIndex put: edge.! !
  7605.  
  7606. !B3DActiveEdgeTable methodsFor: 'testing' stamp: 'ar 4/4/1999 21:21'!
  7607. isEmpty
  7608.     ^stop = 0! !
  7609.  
  7610. !B3DActiveEdgeTable methodsFor: 'enumerating' stamp: 'ar 4/5/1999 02:19'!
  7611. do: aBlock
  7612.     1 to: stop do:[:i| aBlock value: (array at: i)].! !
  7613.  
  7614. !B3DActiveEdgeTable methodsFor: 'private' stamp: 'ar 4/5/1999 02:19'!
  7615. asArray
  7616.     ^array copyFrom: 1 to: stop! !
  7617.  
  7618. !B3DActiveEdgeTable methodsFor: 'private' stamp: 'ar 4/3/1999 05:25'!
  7619. grow
  7620.     | newArray |
  7621.     newArray _ array species new: array size + 100. "Grow linearly"
  7622.     newArray replaceFrom: 1 to: array size with: array startingAt: 1.
  7623.     array _ newArray.! !
  7624.  
  7625. !B3DActiveEdgeTable class methodsFor: 'instance creation' stamp: 'ar 4/4/1999 04:27'!
  7626. new
  7627.     ^super new initialize! !
  7628.  
  7629. !B3DAmbientLight methodsFor: 'shading' stamp: 'ar 2/7/1999 17:16'!
  7630. computeAttenuationFor: distance
  7631.     ^1.0! !
  7632.  
  7633. !B3DAmbientLight methodsFor: 'shading' stamp: 'ar 2/7/1999 16:56'!
  7634. computeDirectionTo: aB3DPrimitiveVertex
  7635.     ^B3DVector3 zero! !
  7636.  
  7637. !B3DAmbientLight methodsFor: 'shading' stamp: 'ar 2/8/1999 00:33'!
  7638. shadeVertexBuffer: vb with: aMaterial into: colorArray
  7639.     "Overridden for simplicity and speed"
  7640.     | color |
  7641.     false ifTrue:[^super shadeVertexBuffer: vb with: aMaterial into: colorArray].
  7642.     self flag: #b3dPrimitive.
  7643.     vb trackAmbientColor ifTrue:[
  7644.         1 to: vb vertexCount do:[:i|
  7645.             color _ (vb primitiveB3dColorAt: i) * lightColor ambientPart.
  7646.             colorArray add: color at: i.
  7647.         ].
  7648.     ] ifFalse:[
  7649.         color _ aMaterial ambientPart * lightColor ambientPart.
  7650.         colorArray += color.
  7651.     ].! !
  7652.  
  7653. !B3DAmbientLight methodsFor: 'testing' stamp: 'ar 2/8/1999 00:33'!
  7654. hasDiffusePart
  7655.     ^false! !
  7656.  
  7657. !B3DAmbientLight methodsFor: 'testing' stamp: 'ar 2/8/1999 00:33'!
  7658. hasSpecularPart
  7659.     ^false! !
  7660.  
  7661. !B3DAmbientLight methodsFor: 'converting' stamp: 'ar 2/15/1999 21:52'!
  7662. asPrimitiveLight
  7663.     "Convert the receiver into a B3DPrimitiveLight"
  7664.     | primLight |
  7665.     primLight _ B3DPrimitiveLight new.
  7666.     primLight ambientPart: lightColor ambientPart.
  7667.     primLight flags: FlagAmbientPart.
  7668.     ^primLight! !
  7669.  
  7670. !B3DAmbientLight methodsFor: 'converting' stamp: 'ar 2/8/1999 01:29'!
  7671. transformedBy: aTransformer
  7672.     ^self! !
  7673.  
  7674. !B3DBox methodsFor: 'displaying' stamp: 'ar 2/16/1999 17:25'!
  7675. renderOn: aRenderer
  7676.     "Note: The use of BoxColors is an example for pre-lighting."
  7677.     1 to: 6 do:[:i|
  7678.         "Enable simple additive computation of box colors.
  7679.         Note: This must be turned on on per-primitive basis."
  7680.         aRenderer
  7681.             trackEmissionColor: true;        "Turn on pre-lit colors"
  7682.             normal: (BoxNormals at: i);
  7683.             color: (BoxColors at: i);        "Set pre-lit color per polygon"
  7684.             drawPolygonAfter:[
  7685.                 aRenderer
  7686.                     texCoords: (vertices at: ((BoxFaceIndexes at: i) at: 1));
  7687.                     vertex: (vertices at: ((BoxFaceIndexes at: i) at: 1));
  7688.                     texCoords: (vertices at: ((BoxFaceIndexes at: i) at: 2));
  7689.                     vertex: (vertices at: ((BoxFaceIndexes at: i) at: 2));
  7690.                     texCoords: (vertices at: ((BoxFaceIndexes at: i) at: 3));
  7691.                     vertex: (vertices at: ((BoxFaceIndexes at: i) at: 3));
  7692.                     texCoords: (vertices at: ((BoxFaceIndexes at: i) at: 4));
  7693.                     vertex: (vertices at: ((BoxFaceIndexes at: i) at: 4)).
  7694.             ].
  7695.     ].! !
  7696.  
  7697. !B3DBox methodsFor: 'private'!
  7698. buildBoxFrom: origin to: corner
  7699.     vertices := Array new: 8.
  7700.     1 to: 8 do:[:i| vertices at: i put: B3DVector3 new].
  7701.  
  7702.     (vertices at: 1) x: origin x.    (vertices at: 1) y: origin y.    (vertices at: 1) z: origin z.
  7703.     (vertices at: 2) x: origin x.    (vertices at: 2) y: origin y.    (vertices at: 2) z: corner z.
  7704.     (vertices at: 3) x: origin x.    (vertices at: 3) y: corner y.    (vertices at: 3) z: corner z.
  7705.     (vertices at: 4) x: origin x.    (vertices at: 4) y: corner y.    (vertices at: 4) z: origin z.
  7706.     (vertices at: 5) x: corner x.    (vertices at: 5) y: origin y.    (vertices at: 5) z: origin z.
  7707.     (vertices at: 6) x: corner x.    (vertices at: 6) y: origin y.    (vertices at: 6) z: corner z.
  7708.     (vertices at: 7) x: corner x.    (vertices at: 7) y: corner y.    (vertices at: 7) z: corner z.
  7709.     (vertices at: 8) x: corner x.    (vertices at: 8) y: corner y.    (vertices at: 8) z: origin z.
  7710. ! !
  7711.  
  7712. !B3DBox methodsFor: 'accessing' stamp: 'ar 3/12/2000 21:11'!
  7713. boundingBox
  7714.     ^Rectangle origin: vertices first corner: (vertices at: 7)! !
  7715.  
  7716. !B3DBox class methodsFor: 'class initialization' stamp: 'ar 2/4/1999 20:20'!
  7717. initialize
  7718.     "B3DBox initialize"
  7719.     | nrmls |
  7720.     nrmls := #(    (-1.0 0.0 0.0) (0.0 1.0 0.0) (1.0 0.0 0.0)
  7721.                 (0.0 -1.0 0.0) (0.0 0.0 1.0) (0.0 0.0 -1.0)) 
  7722.             collect:[:spec| B3DVector3 x: spec first y: spec second z: spec third].
  7723.     BoxNormals := nrmls.
  7724.     "BoxNormals := Array new: 6.
  7725.     1 to: 6 do:[:i|
  7726.         BoxNormals at: i put: (FloatVector3 new).
  7727.         1 to: 3 do:[:j| (BoxNormals at: i) at: j put: ((nrmls at: i) at: j)]]."
  7728.     BoxFaceIndexes := #(    (1 2 3 4) (4 3 7 8) (8 7 6 5)
  7729.                         (5 6 2 1) (6 7 3 2) (8 5 1 4)).
  7730.     BoxColors _ #(red green blue yellow gray cyan) collect:[:s| (Color perform: s) alpha: 0.5].! !
  7731.  
  7732. !B3DBox class methodsFor: 'instance creation'!
  7733. from: origin to: corner
  7734.     ^self new buildBoxFrom: origin to: corner! !
  7735.  
  7736. I represent a simple perspective camera.
  7737.  
  7738. Instance variables:
  7739.     position        <B3DVector3>        where the camera is located
  7740.     target         <B3DVector3>        where the camera is aiming at
  7741.     up             <B3DVector3>        what is considered to be 'up' on screen
  7742.     perspective    <B3DCameraPerspective>    the actual camera perspective!
  7743. !B3DCamera methodsFor: 'accessing'!
  7744. aspectRatio
  7745.     ^perspective aspectRatio! !
  7746.  
  7747. !B3DCamera methodsFor: 'accessing'!
  7748. aspectRatio: aFloat
  7749.     ^perspective aspectRatio: aFloat! !
  7750.  
  7751. !B3DCamera methodsFor: 'accessing' stamp: 'ar 2/8/1999 16:48'!
  7752. direction
  7753.     ^target - position! !
  7754.  
  7755. !B3DCamera methodsFor: 'accessing' stamp: 'ar 2/8/1999 16:48'!
  7756. direction: aVector
  7757.     target _ position + aVector.! !
  7758.  
  7759. !B3DCamera methodsFor: 'accessing'!
  7760. farDistance
  7761.     ^perspective farDistance! !
  7762.  
  7763. !B3DCamera methodsFor: 'accessing'!
  7764. farDistance: aFloat
  7765.     ^perspective farDistance: aFloat! !
  7766.  
  7767. !B3DCamera methodsFor: 'accessing'!
  7768. fieldOfView
  7769.     ^perspective fieldOfView! !
  7770.  
  7771. !B3DCamera methodsFor: 'accessing'!
  7772. fieldOfView: aFloat
  7773.     ^perspective fieldOfView: aFloat! !
  7774.  
  7775. !B3DCamera methodsFor: 'accessing'!
  7776. fov
  7777.     ^self fieldOfView! !
  7778.  
  7779. !B3DCamera methodsFor: 'accessing'!
  7780. fov: aNumber
  7781.     self fieldOfView: aNumber! !
  7782.  
  7783. !B3DCamera methodsFor: 'accessing'!
  7784. nearDistance
  7785.     ^perspective nearDistance! !
  7786.  
  7787. !B3DCamera methodsFor: 'accessing'!
  7788. nearDistance: aFloat
  7789.     ^perspective nearDistance: aFloat! !
  7790.  
  7791. !B3DCamera methodsFor: 'accessing'!
  7792. perspective
  7793.     ^perspective! !
  7794.  
  7795. !B3DCamera methodsFor: 'accessing'!
  7796. perspective: aPerspective
  7797.     perspective _ aPerspective! !
  7798.  
  7799. !B3DCamera methodsFor: 'accessing'!
  7800. position
  7801.     ^position! !
  7802.  
  7803. !B3DCamera methodsFor: 'accessing'!
  7804. position: aVector
  7805.     position _ aVector! !
  7806.  
  7807. !B3DCamera methodsFor: 'accessing'!
  7808. target
  7809.     ^target! !
  7810.  
  7811. !B3DCamera methodsFor: 'accessing'!
  7812. target: aVector
  7813.     target _ aVector! !
  7814.  
  7815. !B3DCamera methodsFor: 'accessing'!
  7816. up
  7817.     ^up! !
  7818.  
  7819. !B3DCamera methodsFor: 'accessing'!
  7820. up: aVector
  7821.     up _ aVector! !
  7822.  
  7823. !B3DCamera methodsFor: 'initialize' stamp: 'ar 3/19/2000 14:12'!
  7824. from3DS: aDictionary
  7825.     "Initialize the receiver from a 3DS camera.
  7826.     Note: #near and #far are NOT clipping planes in 3DS!!"
  7827.     self position: (aDictionary at: #position).
  7828.     self target: (aDictionary at: #target).
  7829.     self up: (0@1@0).
  7830.     self flag: #TODO. "Include #roll value for upDirection"
  7831.     self fieldOfView: 2400.0 / (aDictionary at: #focal).! !
  7832.  
  7833. !B3DCamera methodsFor: 'initialize'!
  7834. from: positionVector to: targetVector up: upVector
  7835.  
  7836.     position := positionVector.
  7837.     target := targetVector.
  7838.     up := upVector.! !
  7839.  
  7840. !B3DCamera methodsFor: 'initialize' stamp: 'ar 2/5/1999 21:22'!
  7841. initialize
  7842.     position := B3DVector3 x: 0.0 y: 0.0 z: 1.0.
  7843.     target := B3DVector3 x: 0.0 y: 0.0 z: 0.0.
  7844.     up := B3DVector3 x: 0.0 y: 1.0 z: 0.0.
  7845.     perspective := B3DCameraPerspective new.
  7846.     self fov: 45.0.
  7847.     self aspectRatio: 1.0.
  7848.     self nearDistance: 0.0001.
  7849.     self farDistance: 10000.0.! !
  7850.  
  7851. !B3DCamera methodsFor: 'initialize' stamp: 'ti 3/27/2000 17:03'!
  7852. setClippingPlanesFrom: anObject
  7853.     "Set the clipping planes from the given object"
  7854.     | box center radius avgDist |
  7855.     box _ anObject boundingBox.
  7856.     center _ (box origin + box corner) * 0.5.
  7857.     radius _ (center - box origin) length.
  7858.     avgDist _ (position - center) length.
  7859.     self farDistance: avgDist + radius.
  7860.     avgDist > radius 
  7861.         ifTrue:[self nearDistance:
  7862.             ((((center - position) normalized
  7863.                 dot: (self direction normalized))
  7864.                     * avgDist - radius) max: 1.0e-31)]
  7865.         ifFalse:[self nearDistance: (self farDistance * 0.00001)].! !
  7866.  
  7867. !B3DCamera methodsFor: 'initialize' stamp: 'ar 2/15/1999 01:04'!
  7868. setTargetFrom: anObject
  7869.     "Make the camera point at the given object"
  7870.     | box |
  7871.     box _ anObject boundingBox.
  7872.     self target: (box origin + box corner) * 0.5.! !
  7873.  
  7874. !B3DCamera methodsFor: 'rendering'!
  7875. renderOn: aRenderer
  7876.     aRenderer
  7877.         lookFrom: self position
  7878.         to: self target
  7879.         up: self up.
  7880.     aRenderer
  7881.         perspective: self perspective.! !
  7882.  
  7883. !B3DCamera methodsFor: 'experimental' stamp: 'ar 2/17/1999 05:41'!
  7884. changeDistanceBy: delta
  7885.     position _ target + (position - target * delta)! !
  7886.  
  7887. !B3DCamera methodsFor: 'experimental' stamp: 'ar 2/17/1999 16:05'!
  7888. moveToFit: aScene
  7889.     "Move the camera to fit the given scene. Experimental."
  7890.     | distance center |
  7891.     self setTargetFrom: aScene.
  7892.     center _ (aScene boundingBox origin + aScene boundingBox corner) * 0.5.
  7893.     distance _ (aScene boundingBox origin - center) length * 1.3.
  7894.     distance _ distance / (target - position) length.
  7895.     "self inform:'Distance ', distance printString."
  7896.     self changeDistanceBy: distance.! !
  7897.  
  7898. !B3DCamera methodsFor: 'experimental' stamp: 'ar 2/15/1999 23:47'!
  7899. rotateBy: angle
  7900.     "Experimental -- rotate around the current up vector by angle degrees.
  7901.     Center at the target point."
  7902.     position _ (B3DMatrix4x4 rotatedBy: angle around: up centeredAt: target) localPointToGlobal: position.! !
  7903.  
  7904. !B3DCamera methodsFor: 'converting' stamp: 'ti 3/22/2000 10:46'!
  7905. asMatrix4x4
  7906.     | xDir yDir zDir m |
  7907.     "calculate z vector"
  7908.     zDir _ self target - self position.
  7909.     zDir safelyNormalize.
  7910.     "calculate x vector"
  7911.     xDir _ self up cross: zDir.
  7912.     xDir safelyNormalize.
  7913.     "recalc y vector"
  7914.     yDir _ zDir cross: xDir.
  7915.     yDir safelyNormalize.
  7916.     m := B3DMatrix4x4 new.
  7917.     m    a11: xDir x;        a12: xDir y;        a13: xDir z;        a14: 0.0;
  7918.         a21: yDir x;        a22: yDir y;        a23: yDir z;        a24: 0.0;
  7919.         a31: zDir x;        a32: zDir y;        a33: zDir z;        a34: 0.0;
  7920.         a41: 0.0;            a42: 0.0;        a43: 0.0;        a44: 1.0.
  7921.     m := m composeWith: (B3DMatrix4x4 identity setTranslation: self position negated).
  7922.     ^m! !
  7923.  
  7924. !B3DCamera class methodsFor: 'instance creation' stamp: 'ar 2/6/1999 23:37'!
  7925. from3DS: aDictionary
  7926.     ^self new from3DS: aDictionary! !
  7927.  
  7928. !B3DCamera class methodsFor: 'instance creation'!
  7929. new
  7930.     ^super new initialize! !
  7931.  
  7932. I represent a perspective projection.
  7933.  
  7934. Instance variables:
  7935.     nearDistance     <Float>    Near clipping plane distance
  7936.     farDistance         <Float>    Far clipping plane distance
  7937.     fieldOfView     <Float>    The field of view covered by the perspective
  7938.     aspectRatio        <Float>     The aspect ratio to be included !
  7939. !B3DCameraPerspective methodsFor: 'converting'!
  7940. asFrustum
  7941.     ^B3DViewingFrustum near: nearDistance far: farDistance fov: fieldOfView aspect: aspectRatio! !
  7942.  
  7943. !B3DCameraPerspective methodsFor: 'converting'!
  7944. asMatrix4x4
  7945.     ^self asFrustum asPerspectiveMatrix! !
  7946.  
  7947. !B3DCameraPerspective methodsFor: 'accessing'!
  7948. aspectRatio
  7949.     ^aspectRatio! !
  7950.  
  7951. !B3DCameraPerspective methodsFor: 'accessing'!
  7952. aspectRatio: aNumber
  7953.     aspectRatio _ aNumber! !
  7954.  
  7955. !B3DCameraPerspective methodsFor: 'accessing'!
  7956. farDistance
  7957.     ^farDistance! !
  7958.  
  7959. !B3DCameraPerspective methodsFor: 'accessing'!
  7960. farDistance: aNumber
  7961.     farDistance _ aNumber! !
  7962.  
  7963. !B3DCameraPerspective methodsFor: 'accessing'!
  7964. fieldOfView
  7965.     ^fieldOfView! !
  7966.  
  7967. !B3DCameraPerspective methodsFor: 'accessing'!
  7968. fieldOfView: aNumber
  7969.     fieldOfView _ aNumber! !
  7970.  
  7971. !B3DCameraPerspective methodsFor: 'accessing'!
  7972. nearDistance
  7973.     ^nearDistance! !
  7974.  
  7975. !B3DCameraPerspective methodsFor: 'accessing'!
  7976. nearDistance: aNumber
  7977.     nearDistance _ aNumber! !
  7978.  
  7979. !B3DClipperPlugin methodsFor: 'primitives' stamp: 'ar 4/18/1999 02:58'!
  7980. b3dClipPolygon
  7981.     "Primitive. Clip the polygon given in the vertexArray using the temporary vertex array which is assumed to have sufficient size."
  7982.     | outMask vtxCount vtxArray tempVtxArray count |
  7983.     self export: true.
  7984.     self inline: false.
  7985.     self var: #vtxArray declareC:'int *vtxArray'.
  7986.     self var: #tempVtxArray declareC:'int *tempVtxArray'.
  7987.     interpreterProxy methodArgumentCount = 4
  7988.         ifFalse:[^interpreterProxy primitiveFail].
  7989.     outMask _ interpreterProxy stackIntegerValue: 0.
  7990.     vtxCount _ interpreterProxy stackIntegerValue: 2.
  7991.     vtxArray _ self stackPrimitiveVertexArray: 3 ofSize: vtxCount + 4.
  7992.     tempVtxArray _ self stackPrimitiveVertexArray: 1 ofSize: vtxCount + 4.
  7993.     (vtxArray == nil or:[tempVtxArray == nil or:[interpreterProxy failed]])
  7994.         ifTrue:[^interpreterProxy primitiveFail].
  7995.     "Hack pointers for one-based indexes"
  7996.     vtxArray _ vtxArray - PrimVertexSize.
  7997.     tempVtxArray _ tempVtxArray - PrimVertexSize.
  7998.     count _ self clipPolygon: vtxArray count: vtxCount with: tempVtxArray mask: outMask.
  7999.     interpreterProxy pop: 4.
  8000.     interpreterProxy pushInteger: count.! !
  8001.  
  8002. !B3DClipperPlugin methodsFor: 'primitives' stamp: 'ar 4/16/1999 01:54'!
  8003. b3dDetermineClipFlags
  8004.     "Primitive. Determine the clipping flags for all vertices."
  8005.     | vtxCount vtxArray result |
  8006.     self export: true.
  8007.     self inline: false.
  8008.     self var: #vtxArray declareC:'void *vtxArray'.
  8009.     interpreterProxy methodArgumentCount = 2
  8010.         ifFalse:[^interpreterProxy primitiveFail].
  8011.     vtxCount _ interpreterProxy stackIntegerValue: 0.
  8012.     interpreterProxy failed ifTrue:[^nil].
  8013.     vtxArray _ self stackPrimitiveVertexArray: 1 ofSize: vtxCount.
  8014.     (vtxArray == nil or:[interpreterProxy failed])
  8015.         ifTrue:[^interpreterProxy primitiveFail].
  8016.     result _ self determineClipFlags: vtxArray count: vtxCount.
  8017.     interpreterProxy failed ifFalse:[
  8018.         interpreterProxy pop: 3.
  8019.         interpreterProxy pushInteger: result.
  8020.     ].! !
  8021.  
  8022. !B3DClipperPlugin methodsFor: 'primitives' stamp: 'ar 4/18/1999 02:59'!
  8023. b3dPrimitiveNextClippedTriangle
  8024.     "Primitive. Return the next clipped triangle from the vertex buffer and return its index."
  8025.     | idxCount vtxCount firstIndex vtxArray idxArray idx1 idx2 idx3 triMask |
  8026.     self export: true.
  8027.     self inline: false.
  8028.     self var: #idxArray declareC:'int *idxArray'.
  8029.     self var: #vtxArray declareC:'int *vtxArray'.
  8030.     interpreterProxy methodArgumentCount = 5
  8031.         ifFalse:[^interpreterProxy primitiveFail].
  8032.     idxCount _ interpreterProxy stackIntegerValue: 0.
  8033.     vtxCount _ interpreterProxy stackIntegerValue: 2.
  8034.     firstIndex _ interpreterProxy stackIntegerValue: 4.
  8035.     interpreterProxy failed ifTrue:[^nil].
  8036.     vtxArray _ self stackPrimitiveVertexArray: 3 ofSize: vtxCount.
  8037.     idxArray _ self stackPrimitiveIndexArray: 1 ofSize: idxCount validate: true forVertexSize: vtxCount.
  8038.     (vtxArray == nil or:[idxArray == nil or:[interpreterProxy failed]])
  8039.         ifTrue:[^interpreterProxy primitiveFail].
  8040.  
  8041.     "Hack idxArray and vtxArray for 1-based indexes"
  8042.     idxArray _ idxArray - 1.
  8043.     vtxArray _ vtxArray - PrimVertexSize.
  8044.     firstIndex to: idxCount by: 3 do:[:i|
  8045.         idx1 _ idxArray at: i.
  8046.         idx2 _ idxArray at: i+1.
  8047.         idx3 _ idxArray at: i+2.
  8048.         (idx1 == 0 or:[idx2 == 0 or:[idx3 == 0]]) ifFalse:[
  8049.             triMask _ ((vtxArray at: idx1 * PrimVertexSize + PrimVtxClipFlags) bitAnd:
  8050.                         ((vtxArray at: idx2 * PrimVertexSize + PrimVtxClipFlags) bitAnd:
  8051.                         (vtxArray at: idx3 * PrimVertexSize + PrimVtxClipFlags))).
  8052.             "Check if tri is completely inside"
  8053.             (InAllMask bitAnd: triMask) = InAllMask ifFalse:[
  8054.                 "Tri is not completely inside -> needs clipping."
  8055.                 (triMask anyMask: OutAllMask) ifTrue:[
  8056.                     "tri is completely outside. Store all zeros"
  8057.                     idxArray at: i put: 0.
  8058.                     idxArray at: i+1 put: 0.
  8059.                     idxArray at: i+2 put: 0.
  8060.                 ] ifFalse:[
  8061.                     "tri must be partially clipped."
  8062.                     interpreterProxy pop: 6. "args + rcvr"
  8063.                     interpreterProxy pushInteger: i.
  8064.                     ^nil
  8065.                 ].
  8066.             ].
  8067.         ].
  8068.     ].
  8069.     "No more entries"
  8070.     interpreterProxy pop: 6. "args + rcvr"
  8071.     interpreterProxy pushInteger: 0.
  8072. ! !
  8073.  
  8074. !B3DClipperPlugin methodsFor: 'clipping' stamp: 'ar 4/16/1999 06:03'!
  8075. clipPolygon: vtxArray count: vtxCount with: tempVtxArray mask: outMask
  8076.     | count |
  8077.     self var: #vtxArray declareC:'int *vtxArray'.
  8078.     self var: #tempVtxArray declareC:'int *tempVtxArray'.
  8079.     "Check if the polygon is outside one boundary only.
  8080.     If so, just do this single clipping operation avoiding multiple enumeration."
  8081.     outMask = OutLeftBit 
  8082.         ifTrue:[^self clipPolygonLeftFrom: tempVtxArray to: vtxArray count: vtxCount].
  8083.     outMask = OutRightBit 
  8084.         ifTrue:[^self clipPolygonRightFrom: tempVtxArray to: vtxArray count: vtxCount].
  8085.     outMask = OutTopBit 
  8086.         ifTrue:[^self clipPolygonTopFrom: tempVtxArray to: vtxArray count: vtxCount].
  8087.     outMask = OutBottomBit 
  8088.         ifTrue:[^self clipPolygonBottomFrom: tempVtxArray to: vtxArray count: vtxCount].
  8089.     outMask = OutFrontBit 
  8090.         ifTrue:[^self clipPolygonFrontFrom: tempVtxArray to: vtxArray count: vtxCount].
  8091.     outMask = OutBackBit 
  8092.         ifTrue:[^self clipPolygonBackFrom: tempVtxArray to: vtxArray count: vtxCount].
  8093.     "Just do each of the clipping operations"
  8094.     count _ vtxCount.
  8095.     count _ self clipPolygonLeftFrom: vtxArray to: tempVtxArray count: count.
  8096.     count = 0 ifTrue:[^0].
  8097.     count _ self clipPolygonRightFrom: tempVtxArray to: vtxArray count: count.
  8098.     count = 0 ifTrue:[^0].
  8099.     count _ self clipPolygonTopFrom: vtxArray to: tempVtxArray count: count.
  8100.     count = 0 ifTrue:[^0].
  8101.     count _ self clipPolygonBottomFrom: tempVtxArray to: vtxArray count: count.
  8102.     count = 0 ifTrue:[^0].
  8103.     count _ self clipPolygonFrontFrom: vtxArray to: tempVtxArray count: count.
  8104.     count = 0 ifTrue:[^0].
  8105.     count _ self clipPolygonBackFrom: tempVtxArray to: vtxArray count: count.
  8106.     ^count! !
  8107.  
  8108. !B3DClipperPlugin methodsFor: 'clipping' stamp: 'ar 4/16/1999 01:57'!
  8109. determineClipFlags: vtxArray count: count
  8110.     | vtxPtr fullMask w w2 flags x y z |
  8111.     self var: #vtxPtr declareC:'float *vtxPtr'.
  8112.     self var: #vtxArray declareC:'void *vtxArray'.
  8113.     self var: #x declareC:'double x'.
  8114.     self var: #y declareC:'double y'.
  8115.     self var: #z declareC:'double z'.
  8116.     self var: #w declareC:'double w'.
  8117.     self var: #w2 declareC:'double w2'.
  8118.     vtxPtr _ self cCoerce: vtxArray to: 'float *'.
  8119.     fullMask _ InAllMask + OutAllMask.
  8120.     1 to: count do:[:i|
  8121.         w _ vtxPtr at: PrimVtxRasterPosW.
  8122.         w2 _ 0.0 - w.
  8123.         flags _ 0.
  8124.         x _ vtxPtr at: PrimVtxRasterPosX.
  8125.         x >= w2 ifTrue:[flags _ flags bitOr: InLeftBit] ifFalse:[flags _ flags bitOr: OutLeftBit].
  8126.         x <= w ifTrue:[flags _ flags bitOr: InRightBit] ifFalse:[flags _ flags bitOr: OutRightBit].
  8127.         y _ vtxPtr at: PrimVtxRasterPosY.
  8128.         y >= w2 ifTrue:[flags _ flags bitOr: InBottomBit] ifFalse:[flags _ flags bitOr: OutBottomBit].
  8129.         y <= w ifTrue:[flags _ flags bitOr: InTopBit] ifFalse:[flags _ flags bitOr: OutTopBit].
  8130.         z _ vtxPtr at: PrimVtxRasterPosZ.
  8131.         z >= w2 ifTrue:[flags _ flags bitOr: InFrontBit] ifFalse:[flags _ flags bitOr: OutFrontBit].
  8132.         z <= w ifTrue:[flags _ flags bitOr: InBackBit] ifFalse:[flags _ flags bitOr: OutBackBit].
  8133.         fullMask _ fullMask bitAnd: flags.
  8134.         (self cCoerce: vtxPtr to:'int *') at: PrimVtxClipFlags put: flags.
  8135.         vtxPtr _ vtxPtr + PrimVertexSize.
  8136.     ].
  8137.     ^fullMask! !
  8138.  
  8139. !B3DClipperPlugin methodsFor: 'clipping' stamp: 'ar 4/21/1999 01:26'!
  8140. interpolateFrom: last to: next at: t into: out
  8141.     "Interpolate the primitive vertices last/next at the parameter t"
  8142.     | delta rgbaLast lastValue rgbaNext nextValue newValue x y z w w2 flags |
  8143.     self var: #last declareC:'float *last'.
  8144.     self var: #next declareC:'float *next'.
  8145.     self var: #out declareC:'float *out'.
  8146.     self var: #t declareC: 'double t'.
  8147.     self var: #delta declareC: 'double delta'.
  8148.     self var: #rgbaLast declareC:'unsigned int rgbaLast'.
  8149.     self var: #rgbaNext declareC:'unsigned int rgbaNext'.
  8150.     self var: #lastValue declareC:'unsigned int lastValue'.
  8151.     self var: #nextValue declareC:'unsigned int nextValue'.
  8152.     self var: #newValue declareC:'unsigned int newValue'.
  8153.     self var: #x declareC:'double x'.
  8154.     self var: #y declareC:'double y'.
  8155.     self var: #z declareC:'double z'.
  8156.     self var: #w declareC:'double w'.
  8157.     self var: #w2 declareC:'double w2'.
  8158.     "Interpolate raster position"
  8159.     delta _ (next at: PrimVtxRasterPosX) - (last at: PrimVtxRasterPosX).
  8160.     x _ (last at: PrimVtxRasterPosX) + (delta * t).
  8161.     out at: PrimVtxRasterPosX put: (self cCoerce: x to: 'float').
  8162.     delta _ (next at: PrimVtxRasterPosY) - (last at: PrimVtxRasterPosY).
  8163.     y _ (last at: PrimVtxRasterPosY) + (delta * t).
  8164.     out at: PrimVtxRasterPosY put: (self cCoerce: y to: 'float').
  8165.     delta _ (next at: PrimVtxRasterPosZ) - (last at: PrimVtxRasterPosZ).
  8166.     z _ (last at: PrimVtxRasterPosZ) + (delta * t).
  8167.     out at: PrimVtxRasterPosZ put: (self cCoerce: z to: 'float').
  8168.     delta _ (next at: PrimVtxRasterPosW) - (last at: PrimVtxRasterPosW).
  8169.     w _ (last at: PrimVtxRasterPosW) + (delta * t).
  8170.     out at: PrimVtxRasterPosW put: (self cCoerce: w to: 'float').
  8171.     "Determine new clipFlags"
  8172.     w2 _ 0.0 - w.
  8173.     flags _ 0.
  8174.     x >= w2 ifTrue:[flags _ flags bitOr: InLeftBit] ifFalse:[flags _ flags bitOr: OutLeftBit].
  8175.     x <= w ifTrue:[flags _ flags bitOr: InRightBit] ifFalse:[flags _ flags bitOr: OutRightBit].
  8176.     y >= w2 ifTrue:[flags _ flags bitOr: InBottomBit] ifFalse:[flags _ flags bitOr: OutBottomBit].
  8177.     y <= w ifTrue:[flags _ flags bitOr: InTopBit] ifFalse:[flags _ flags bitOr: OutTopBit].
  8178.     z >= w2 ifTrue:[flags _ flags bitOr: InFrontBit] ifFalse:[flags _ flags bitOr: OutFrontBit].
  8179.     z <= w ifTrue:[flags _ flags bitOr: InBackBit] ifFalse:[flags _ flags bitOr: OutBackBit].
  8180.     (self cCoerce: out to: 'int *') at: PrimVtxClipFlags put: flags.
  8181.  
  8182.     "Interpolate color"
  8183.     rgbaLast _ (self cCoerce: last to:'unsigned int *') at: PrimVtxColor32.
  8184.     lastValue _ rgbaLast bitAnd: 255. rgbaLast _ rgbaLast >> 8.
  8185.     rgbaNext _ (self cCoerce: next to: 'unsigned int *') at: PrimVtxColor32.
  8186.     nextValue _ rgbaNext bitAnd: 255. rgbaNext _ rgbaNext >> 8.
  8187.     delta _ (self cCoerce: (nextValue - lastValue) to:'int') * t.
  8188.     newValue _ (lastValue + delta) asInteger.
  8189.  
  8190.     lastValue _ rgbaLast bitAnd: 255. rgbaLast _ rgbaLast >> 8.
  8191.     nextValue _ rgbaNext bitAnd: 255. rgbaNext _ rgbaNext >> 8.
  8192.     delta _ (self cCoerce: (nextValue - lastValue) to:'int') * t.
  8193.     newValue _ newValue + ((lastValue + delta) asInteger << 8).
  8194.  
  8195.     lastValue _ rgbaLast bitAnd: 255. rgbaLast _ rgbaLast >> 8.
  8196.     nextValue _ rgbaNext bitAnd: 255. rgbaNext _ rgbaNext >> 8.
  8197.     delta _ (self cCoerce: (nextValue - lastValue) to:'int') * t.
  8198.     newValue _ newValue + ((lastValue + delta) asInteger << 16).
  8199.  
  8200.     lastValue _ rgbaLast bitAnd: 255.
  8201.     nextValue _ rgbaNext bitAnd: 255.
  8202.     delta _ (self cCoerce: (nextValue - lastValue) to:'int') * t.
  8203.     newValue _ newValue + ((lastValue + delta) asInteger << 24).
  8204.  
  8205.     (self cCoerce: out to:'unsigned int*') at: PrimVtxColor32 put: newValue.
  8206.  
  8207.     "Interpolate texture coordinates"
  8208.     delta _ (next at: PrimVtxTexCoordU) - (last at: PrimVtxTexCoordU).
  8209.     out at: PrimVtxTexCoordU put: (self cCoerce: (last at: PrimVtxTexCoordU) + (delta * t) to:'float').
  8210.     delta _ (next at: PrimVtxTexCoordV) - (last at: PrimVtxTexCoordV).
  8211.     out at: PrimVtxTexCoordV put: (self cCoerce: (last at: PrimVtxTexCoordV) + (delta * t) to:'float').
  8212. ! !
  8213.  
  8214. !B3DClipperPlugin methodsFor: 'clipping utilities' stamp: 'ar 4/16/1999 01:56'!
  8215. backClipValueFrom: last to: next
  8216.     self returnTypeC:'double'.
  8217.     ^(((self cCoerce: last to: 'float *') at: PrimVtxRasterPosZ) - 
  8218.         ((self cCoerce: last to:'float *') at: PrimVtxRasterPosW)) /
  8219.  
  8220.     (
  8221.     (((self cCoerce: next to:'float *') at: PrimVtxRasterPosW) -
  8222.         ((self cCoerce: last to: 'float *') at: PrimVtxRasterPosW))
  8223.     -
  8224.      (((self cCoerce: next to:'float *') at: PrimVtxRasterPosZ) -
  8225.         ((self cCoerce: last to:'float *') at: PrimVtxRasterPosZ))
  8226.     ).! !
  8227.  
  8228. !B3DClipperPlugin methodsFor: 'clipping utilities' stamp: 'ar 4/16/1999 06:43'!
  8229. bottomClipValueFrom: last to: next
  8230.     self returnTypeC:'double'.
  8231.     ^(0.0 - (((self cCoerce: last to: 'float *') at: PrimVtxRasterPosY) + 
  8232.         ((self cCoerce: last to:'float *') at: PrimVtxRasterPosW))) /
  8233.  
  8234.     (
  8235.     (((self cCoerce: next to:'float *') at: PrimVtxRasterPosW) -
  8236.         ((self cCoerce: last to: 'float *') at: PrimVtxRasterPosW))
  8237.     +
  8238.      (((self cCoerce: next to:'float *') at: PrimVtxRasterPosY) -
  8239.         ((self cCoerce: last to:'float *') at: PrimVtxRasterPosY))
  8240.     ).! !
  8241.  
  8242. !B3DClipperPlugin methodsFor: 'clipping utilities' stamp: 'ar 4/17/1999 22:18'!
  8243. clipPolygonBackFrom: buf1 to: buf2 count: n
  8244.     | last next t outIndex inLast inNext |
  8245.     self var: #buf1 declareC:'int *buf1'.
  8246.     self var: #buf2 declareC:'int *buf2'.
  8247.     self var: #last declareC:'int *last'.
  8248.     self var: #next declareC:'int *next'.
  8249.     self var: #t declareC: 'double t'.
  8250.     outIndex _ 0.
  8251.     last _ buf1 + (n * PrimVertexSize).
  8252.     next _ buf1 + PrimVertexSize.
  8253.     inLast _ (last at: PrimVtxClipFlags) anyMask: InBackBit.
  8254.     1 to: n do:[:i|
  8255.         inNext _ (next at: PrimVtxClipFlags) anyMask: InBackBit.
  8256.         inLast = inNext ifFalse:["Passes clip boundary"
  8257.             t _ self backClipValueFrom: last to: next.
  8258.             outIndex _ outIndex + 1.
  8259.             self interpolateFrom: (self cCoerce: last to:'float *')
  8260.                 to: (self cCoerce: next to:'float *')
  8261.                 at: t 
  8262.                 into: (self cCoerce: (buf2 + (outIndex * PrimVertexSize)) to:'float*')].
  8263.         inNext ifTrue:[
  8264.             outIndex _ outIndex+1.
  8265.             0 to: PrimVertexSize-1 do:[:j|
  8266.                 buf2 at: (outIndex*PrimVertexSize + j) put: (next at: j)].
  8267.         ].
  8268.         last _ next.
  8269.         inLast _ inNext.
  8270.         next _ next + PrimVertexSize.
  8271.     ].
  8272.     ^outIndex! !
  8273.  
  8274. !B3DClipperPlugin methodsFor: 'clipping utilities' stamp: 'ar 4/17/1999 22:18'!
  8275. clipPolygonBottomFrom: buf1 to: buf2 count: n
  8276.     | last next t outIndex inLast inNext |
  8277.     self var: #buf1 declareC:'int *buf1'.
  8278.     self var: #buf2 declareC:'int *buf2'.
  8279.     self var: #last declareC:'int *last'.
  8280.     self var: #next declareC:'int *next'.
  8281.     self var: #t declareC: 'double t'.
  8282.     outIndex _ 0.
  8283.     last _ buf1 + (n * PrimVertexSize).
  8284.     next _ buf1 + PrimVertexSize.
  8285.     inLast _ (last at: PrimVtxClipFlags) anyMask: InBottomBit.
  8286.     1 to: n do:[:i|
  8287.         inNext _ (next at: PrimVtxClipFlags) anyMask: InBottomBit.
  8288.         inLast = inNext ifFalse:["Passes clip boundary"
  8289.             t _ self bottomClipValueFrom: last to: next.
  8290.             outIndex _ outIndex + 1.
  8291.             self interpolateFrom: (self cCoerce: last to:'float *')
  8292.                 to: (self cCoerce: next to:'float *')
  8293.                 at: t 
  8294.                 into: (self cCoerce: (buf2 + (outIndex * PrimVertexSize)) to:'float*')].
  8295.         inNext ifTrue:[
  8296.             outIndex _ outIndex+1.
  8297.             0 to: PrimVertexSize-1 do:[:j|
  8298.                 buf2 at: (outIndex*PrimVertexSize + j) put: (next at: j)].
  8299.         ].
  8300.         last _ next.
  8301.         inLast _ inNext.
  8302.         next _ next + PrimVertexSize.
  8303.     ].
  8304.     ^outIndex! !
  8305.  
  8306. !B3DClipperPlugin methodsFor: 'clipping utilities' stamp: 'ar 4/17/1999 22:18'!
  8307. clipPolygonFrontFrom: buf1 to: buf2 count: n
  8308.     | last next t outIndex inLast inNext |
  8309.     self var: #buf1 declareC:'int *buf1'.
  8310.     self var: #buf2 declareC:'int *buf2'.
  8311.     self var: #last declareC:'int *last'.
  8312.     self var: #next declareC:'int *next'.
  8313.     self var: #t declareC: 'double t'.
  8314.     outIndex _ 0.
  8315.     last _ buf1 + (n * PrimVertexSize).
  8316.     next _ buf1 + PrimVertexSize.
  8317.     inLast _ (last at: PrimVtxClipFlags) anyMask: InFrontBit.
  8318.     1 to: n do:[:i|
  8319.         inNext _ (next at: PrimVtxClipFlags) anyMask: InFrontBit.
  8320.         inLast = inNext ifFalse:["Passes clip boundary"
  8321.             t _ self frontClipValueFrom: last to: next.
  8322.             outIndex _ outIndex + 1.
  8323.             self interpolateFrom: (self cCoerce: last to:'float *')
  8324.                 to: (self cCoerce: next to:'float *')
  8325.                 at: t 
  8326.                 into: (self cCoerce: (buf2 + (outIndex * PrimVertexSize)) to:'float*')].
  8327.         inNext ifTrue:[
  8328.             outIndex _ outIndex+1.
  8329.             0 to: PrimVertexSize-1 do:[:j|
  8330.                 buf2 at: (outIndex*PrimVertexSize + j) put: (next at: j)].
  8331.         ].
  8332.         last _ next.
  8333.         inLast _ inNext.
  8334.         next _ next + PrimVertexSize.
  8335.     ].
  8336.     ^outIndex! !
  8337.  
  8338. !B3DClipperPlugin methodsFor: 'clipping utilities' stamp: 'ar 4/17/1999 22:18'!
  8339. clipPolygonLeftFrom: buf1 to: buf2 count: n
  8340.     | last next t outIndex inLast inNext |
  8341.     self var: #buf1 declareC:'int *buf1'.
  8342.     self var: #buf2 declareC:'int *buf2'.
  8343.     self var: #last declareC:'int *last'.
  8344.     self var: #next declareC:'int *next'.
  8345.     self var: #t declareC: 'double t'.
  8346.     outIndex _ 0.
  8347.     last _ buf1 + (n * PrimVertexSize).
  8348.     next _ buf1 + PrimVertexSize.
  8349.     inLast _ (last at: PrimVtxClipFlags) anyMask: InLeftBit.
  8350.     1 to: n do:[:i|
  8351.         inNext _ (next at: PrimVtxClipFlags) anyMask: InLeftBit.
  8352.         inLast = inNext ifFalse:["Passes clip boundary"
  8353.             t _ self leftClipValueFrom: last to: next.
  8354.             outIndex _ outIndex + 1.
  8355.             self interpolateFrom: (self cCoerce: last to:'float *')
  8356.                 to: (self cCoerce: next to:'float *')
  8357.                 at: t 
  8358.                 into: (self cCoerce: (buf2 + (outIndex * PrimVertexSize)) to:'float*')].
  8359.         inNext ifTrue:[
  8360.             outIndex _ outIndex+1.
  8361.             0 to: PrimVertexSize-1 do:[:j|
  8362.                 buf2 at: (outIndex*PrimVertexSize + j) put: (next at: j)].
  8363.         ].
  8364.         last _ next.
  8365.         inLast _ inNext.
  8366.         next _ next + PrimVertexSize.
  8367.     ].
  8368.     ^outIndex! !
  8369.  
  8370. !B3DClipperPlugin methodsFor: 'clipping utilities' stamp: 'ar 4/17/1999 22:18'!
  8371. clipPolygonRightFrom: buf1 to: buf2 count: n
  8372.     | last next t outIndex inLast inNext |
  8373.     self var: #buf1 declareC:'int *buf1'.
  8374.     self var: #buf2 declareC:'int *buf2'.
  8375.     self var: #last declareC:'int *last'.
  8376.     self var: #next declareC:'int *next'.
  8377.     self var: #t declareC: 'double t'.
  8378.     outIndex _ 0.
  8379.     last _ buf1 + (n * PrimVertexSize).
  8380.     next _ buf1 + PrimVertexSize.
  8381.     inLast _ (last at: PrimVtxClipFlags) anyMask: InRightBit.
  8382.     1 to: n do:[:i|
  8383.         inNext _ (next at: PrimVtxClipFlags) anyMask: InRightBit.
  8384.         inLast = inNext ifFalse:["Passes clip boundary"
  8385.             t _ self rightClipValueFrom: last to: next.
  8386.             outIndex _ outIndex + 1.
  8387.             self interpolateFrom: (self cCoerce: last to:'float *')
  8388.                 to: (self cCoerce: next to:'float *')
  8389.                 at: t 
  8390.                 into: (self cCoerce: (buf2 + (outIndex * PrimVertexSize)) to:'float*')].
  8391.         inNext ifTrue:[
  8392.             outIndex _ outIndex+1.
  8393.             0 to: PrimVertexSize-1 do:[:j|
  8394.                 buf2 at: (outIndex*PrimVertexSize + j) put: (next at: j)].
  8395.         ].
  8396.         last _ next.
  8397.         inLast _ inNext.
  8398.         next _ next + PrimVertexSize.
  8399.     ].
  8400.     ^outIndex! !
  8401.  
  8402. !B3DClipperPlugin methodsFor: 'clipping utilities' stamp: 'ar 4/17/1999 22:19'!
  8403. clipPolygonTopFrom: buf1 to: buf2 count: n
  8404.     | last next t outIndex inLast inNext |
  8405.     self var: #buf1 declareC:'int *buf1'.
  8406.     self var: #buf2 declareC:'int *buf2'.
  8407.     self var: #last declareC:'int *last'.
  8408.     self var: #next declareC:'int *next'.
  8409.     self var: #t declareC: 'double t'.
  8410.     outIndex _ 0.
  8411.     last _ buf1 + (n * PrimVertexSize).
  8412.     next _ buf1 + PrimVertexSize.
  8413.     inLast _ (last at: PrimVtxClipFlags) anyMask: InTopBit.
  8414.     1 to: n do:[:i|
  8415.         inNext _ (next at: PrimVtxClipFlags) anyMask: InTopBit.
  8416.         inLast = inNext ifFalse:["Passes clip boundary"
  8417.             t _ self topClipValueFrom: last to: next.
  8418.             outIndex _ outIndex + 1.
  8419.             self interpolateFrom: (self cCoerce: last to:'float *')
  8420.                 to: (self cCoerce: next to:'float *')
  8421.                 at: t 
  8422.                 into: (self cCoerce: (buf2 + (outIndex * PrimVertexSize)) to:'float*')].
  8423.         inNext ifTrue:[
  8424.             outIndex _ outIndex+1.
  8425.             0 to: PrimVertexSize-1 do:[:j|
  8426.                 buf2 at: (outIndex*PrimVertexSize + j) put: (next at: j)].
  8427.         ].
  8428.         last _ next.
  8429.         inLast _ inNext.
  8430.         next _ next + PrimVertexSize.
  8431.     ].
  8432.     ^outIndex! !
  8433.  
  8434. !B3DClipperPlugin methodsFor: 'clipping utilities' stamp: 'ar 4/16/1999 06:43'!
  8435. frontClipValueFrom: last to: next
  8436.     self returnTypeC:'double'.
  8437.     ^(0.0 - (((self cCoerce: last to: 'float *') at: PrimVtxRasterPosZ) + 
  8438.         ((self cCoerce: last to:'float *') at: PrimVtxRasterPosW))) /
  8439.  
  8440.     (
  8441.     (((self cCoerce: next to:'float *') at: PrimVtxRasterPosW) -
  8442.         ((self cCoerce: last to: 'float *') at: PrimVtxRasterPosW))
  8443.     +
  8444.      (((self cCoerce: next to:'float *') at: PrimVtxRasterPosZ) -
  8445.         ((self cCoerce: last to:'float *') at: PrimVtxRasterPosZ))
  8446.     ).! !
  8447.  
  8448. !B3DClipperPlugin methodsFor: 'clipping utilities' stamp: 'ar 4/16/1999 06:43'!
  8449. leftClipValueFrom: last to: next
  8450.     self returnTypeC:'double'.
  8451.     ^(0.0 - (((self cCoerce: last to: 'float *') at: PrimVtxRasterPosX) + 
  8452.         ((self cCoerce: last to:'float *') at: PrimVtxRasterPosW))) /
  8453.  
  8454.     (
  8455.     (((self cCoerce: next to:'float *') at: PrimVtxRasterPosW) -
  8456.         ((self cCoerce: last to: 'float *') at: PrimVtxRasterPosW))
  8457.     +
  8458.      (((self cCoerce: next to:'float *') at: PrimVtxRasterPosX) -
  8459.         ((self cCoerce: last to:'float *') at: PrimVtxRasterPosX))
  8460.     ).! !
  8461.  
  8462. !B3DClipperPlugin methodsFor: 'clipping utilities' stamp: 'ar 4/16/1999 01:56'!
  8463. rightClipValueFrom: last to: next
  8464.     self returnTypeC:'double'.
  8465.     ^(((self cCoerce: last to: 'float *') at: PrimVtxRasterPosX) - 
  8466.         ((self cCoerce: last to:'float *') at: PrimVtxRasterPosW)) /
  8467.  
  8468.     (
  8469.     (((self cCoerce: next to:'float *') at: PrimVtxRasterPosW) -
  8470.         ((self cCoerce: last to: 'float *') at: PrimVtxRasterPosW))
  8471.     -
  8472.      (((self cCoerce: next to:'float *') at: PrimVtxRasterPosX) -
  8473.         ((self cCoerce: last to:'float *') at: PrimVtxRasterPosX))
  8474.     ).! !
  8475.  
  8476. !B3DClipperPlugin methodsFor: 'clipping utilities' stamp: 'ar 4/16/1999 01:56'!
  8477. topClipValueFrom: last to: next
  8478.     self returnTypeC:'double'.
  8479.     ^(((self cCoerce: last to: 'float *') at: PrimVtxRasterPosY) - 
  8480.         ((self cCoerce: last to:'float *') at: PrimVtxRasterPosW)) /
  8481.  
  8482.     (
  8483.     (((self cCoerce: next to:'float *') at: PrimVtxRasterPosW) -
  8484.         ((self cCoerce: last to: 'float *') at: PrimVtxRasterPosW))
  8485.     -
  8486.      (((self cCoerce: next to:'float *') at: PrimVtxRasterPosY) -
  8487.         ((self cCoerce: last to:'float *') at: PrimVtxRasterPosY))
  8488.     ).! !
  8489.  
  8490. I represent an RGBA color value in floating point format. I am used during the lighting and shading computations.!
  8491. !B3DColor4 methodsFor: 'accessing'!
  8492. alpha
  8493.     ^self floatAt: 4! !
  8494.  
  8495. !B3DColor4 methodsFor: 'accessing'!
  8496. alpha: aNumber
  8497.     self floatAt: 4 put: aNumber! !
  8498.  
  8499. !B3DColor4 methodsFor: 'accessing'!
  8500. blue
  8501.     ^self floatAt: 3! !
  8502.  
  8503. !B3DColor4 methodsFor: 'accessing'!
  8504. blue: aNumber
  8505.     self floatAt: 3 put: aNumber! !
  8506.  
  8507. !B3DColor4 methodsFor: 'accessing'!
  8508. green
  8509.     ^self floatAt: 2! !
  8510.  
  8511. !B3DColor4 methodsFor: 'accessing'!
  8512. green: aNumber
  8513.     self floatAt: 2 put: aNumber! !
  8514.  
  8515. !B3DColor4 methodsFor: 'accessing'!
  8516. red
  8517.     ^self floatAt: 1! !
  8518.  
  8519. !B3DColor4 methodsFor: 'accessing'!
  8520. red: aNumber
  8521.     self floatAt: 1 put: aNumber! !
  8522.  
  8523. !B3DColor4 methodsFor: 'converting' stamp: 'ar 5/4/2000 17:59'!
  8524. asB3DColor
  8525.     ^self! !
  8526.  
  8527. !B3DColor4 methodsFor: 'converting'!
  8528. asColor
  8529.     ^Color r: self red g: self green b: self blue alpha: self alpha! !
  8530.  
  8531. !B3DColor4 methodsFor: 'converting' stamp: 'ar 2/4/1999 20:21'!
  8532. pixelValue32
  8533.     ^self asColor pixelWordForDepth: 32! !
  8534.  
  8535. !B3DColor4 methodsFor: 'private'!
  8536. privateLoadFrom: srcObject
  8537.     | color |
  8538.     color _ srcObject asColor.
  8539.     self red: color red.
  8540.     self green: color green.
  8541.     self blue: color blue.
  8542.     self alpha: color alpha.! !
  8543.  
  8544. !B3DColor4 methodsFor: 'initialize' stamp: 'ar 2/7/1999 16:21'!
  8545. r: rValue g: gValue b: bValue a: aValue
  8546.     self red: rValue.
  8547.     self green: gValue.
  8548.     self blue: bValue.
  8549.     self alpha: aValue.! !
  8550.  
  8551. !B3DColor4 methodsFor: 'testing' stamp: 'ar 2/15/1999 22:12'!
  8552. isZero
  8553.     ^self alpha isZero! !
  8554.  
  8555. !B3DColor4 methodsFor: 'interpolating' stamp: 'jsp 2/8/1999 19:57'!
  8556. interpolateTo: end at: amountDone
  8557.     "Return the color vector yielded by interpolating from the state of the object to the specified end state at the specified amount done"
  8558.  
  8559.     | newColor r g b a |
  8560.     r _ self red.
  8561.     g _ self green.
  8562.     b _ self blue.
  8563.     a _ self alpha.
  8564.  
  8565.     newColor _ B3DColor4 new.
  8566.     newColor red: r + (((end red) - r) * amountDone).
  8567.     newColor green: g + (((end green) - g) * amountDone).
  8568.     newColor blue: b + (((end blue) - b) * amountDone).
  8569.     newColor alpha: a + (((end alpha) - a) * amountDone).
  8570.  
  8571.     ^ newColor.
  8572. ! !
  8573.  
  8574. !B3DColor4 class methodsFor: 'instance creation' stamp: 'ar 2/1/1999 21:22'!
  8575. numElements
  8576.     ^4! !
  8577.  
  8578. !B3DColor4 class methodsFor: 'instance creation' stamp: 'ar 2/7/1999 16:21'!
  8579. r: rValue g: gValue b: bValue a: aValue
  8580.     ^self new r: rValue g: gValue b: bValue a: aValue! !
  8581.  
  8582. !B3DColor4 class methodsFor: 'instance creation' stamp: 'jsp 2/8/1999 18:46'!
  8583. red: r green: g blue: b alpha: a
  8584.     "Create an initialize a color vector."
  8585.  
  8586.     | newColor |
  8587.     newColor _ B3DColor4 new.
  8588.  
  8589.     newColor red: r.
  8590.     newColor green: g.
  8591.     newColor blue: b.
  8592.     newColor alpha: a.
  8593.  
  8594.     ^ newColor.
  8595. ! !
  8596.  
  8597. I am an inplace storage area for B3DColor4 items used during lighting and shading.!
  8598. !B3DColor4Array methodsFor: 'special ops' stamp: 'ar 2/4/1999 01:50'!
  8599. += aColor
  8600.     "Add the given color to all the elements in the receiver"
  8601.     | r g b a |
  8602.     r _ aColor red.
  8603.     g _ aColor green.
  8604.     b _ aColor blue.
  8605.     a _ aColor alpha.
  8606.     1 to: self basicSize by: 4 do:[:i|
  8607.         self floatAt: i put: (self floatAt: i) + r.
  8608.         self floatAt: i+1 put: (self floatAt: i+1) + g.
  8609.         self floatAt: i+2 put: (self floatAt: i+2) + b.
  8610.         self floatAt: i+3 put: (self floatAt: i+3) + a.
  8611.     ].! !
  8612.  
  8613. !B3DColor4Array methodsFor: 'special ops' stamp: 'ar 2/7/1999 16:44'!
  8614. add: aB3dColor4 at: index
  8615.     | baseIdx |
  8616.     baseIdx _ index-1*4.
  8617.     self floatAt: baseIdx+1 put: (self floatAt: baseIdx+1) + aB3dColor4 red.
  8618.     self floatAt: baseIdx+2 put: (self floatAt: baseIdx+2) + aB3dColor4 green.
  8619.     self floatAt: baseIdx+3 put: (self floatAt: baseIdx+3) + aB3dColor4 blue.
  8620.     self floatAt: baseIdx+4 put: (self floatAt: baseIdx+4) + aB3dColor4 alpha.
  8621. ! !
  8622.  
  8623. !B3DColor4Array methodsFor: 'special ops'!
  8624. clampAllFrom: minValue to: maxValue
  8625.     "Clamp all elements in the receiver to be in the range (minValue, maxValue)"
  8626.     | value |
  8627.     1 to: self basicSize do:[:i|
  8628.         value _ self floatAt: i.
  8629.         value _ value min: maxValue.
  8630.         value _ value max: minValue.
  8631.         self floatAt: i put: value.
  8632.     ].! !
  8633.  
  8634. !B3DColor4Array methodsFor: 'special ops'!
  8635. fillWith: anInteger
  8636.     <primitive: 145>
  8637.     self primitiveFailed! !
  8638.  
  8639. !B3DColor4Array class methodsFor: 'instance creation' stamp: 'ar 2/5/1999 22:50'!
  8640. contentsClass
  8641.     ^B3DColor4! !
  8642.  
  8643. !B3DDirectionalLight methodsFor: 'shading' stamp: 'ar 2/7/1999 16:54'!
  8644. computeAttenuationFor: distance
  8645.     "Since a directional light is positioned at virtual infinity, it cannot have any attenuation"
  8646.     ^1.0! !
  8647.  
  8648. !B3DDirectionalLight methodsFor: 'shading' stamp: 'ar 2/7/1999 16:53'!
  8649. computeDirectionTo: aB3DPrimitiveVertex
  8650.     "A directional light has an explicit direction regardless of the vertex position"
  8651.     ^direction! !
  8652.  
  8653. !B3DDirectionalLight methodsFor: 'converting' stamp: 'ar 2/15/1999 21:55'!
  8654. asPrimitiveLight
  8655.     "Convert the receiver into a B3DPrimitiveLight"
  8656.     | primLight flags |
  8657.     primLight _ B3DPrimitiveLight new.
  8658.     primLight direction: direction.
  8659.     flags _ FlagDirectional.
  8660.     lightColor ambientPart isZero ifFalse:[
  8661.         primLight ambientPart: lightColor ambientPart.
  8662.         flags _ flags bitOr: FlagAmbientPart].
  8663.     lightColor diffusePart isZero ifFalse:[
  8664.         primLight diffusePart: lightColor diffusePart.
  8665.         flags _ flags bitOr: FlagDiffusePart].
  8666.     lightColor specularPart isZero ifFalse:[
  8667.         primLight specularPart: lightColor specularPart.
  8668.         flags _ flags bitOr: FlagSpecularPart].
  8669.     primLight flags: flags.
  8670.     ^primLight! !
  8671.  
  8672. !B3DDirectionalLight methodsFor: 'converting' stamp: 'ar 2/8/1999 01:28'!
  8673. transformedBy: aTransformer
  8674.     ^(super transformedBy: aTransformer) direction: (aTransformer transformDirection: direction)! !
  8675.  
  8676. I represent a hardware accelerated 3D display. Usually, this means some sort of offscreen buffer (so that we can do efficient compositing for the 2D case) but it might be different.
  8677.  
  8678. The first implementation uses Direct3D on Windows where compositing is trivially achieved by using DirectDrawSurfaces which can be accessed by either 2D or 3D operations.!
  8679. !B3DDisplayScreen methodsFor: 'testing' stamp: 'ar 5/27/2000 17:16'!
  8680. isB3DDisplayScreen
  8681.     ^true! !
  8682.  
  8683. !B3DDisplayScreen methodsFor: 'primitives-display' stamp: 'ar 5/28/2000 01:47'!
  8684. primBltFast: displayHandle from: sourceHandle at: destOrigin from: sourceOrigin extent: extent
  8685.     <primitive:'primitiveBltToDisplay' module:'Squeak3DX'>
  8686.     ^nil! !
  8687.  
  8688. !B3DDisplayScreen methodsFor: 'primitives-display' stamp: 'ar 5/28/2000 01:47'!
  8689. primBltFast: displayHandle to: dstHandle at: destOrigin from: sourceOrigin extent: extent
  8690.     "Primitive. Perform a fast blt operation. Return the receiver if successful."
  8691.     <primitive:'primitiveBltFromDisplay' module:'Squeak3DX'>
  8692.     ^nil! !
  8693.  
  8694. !B3DDisplayScreen methodsFor: 'primitives-display' stamp: 'ar 5/27/2000 17:18'!
  8695. primCreateDisplaySurface: d width: w height: h
  8696.     "Primitive. Create a new external display surface. Return the handle used to identify the receiver. Fail if the surface cannot be created."
  8697.     <primitive:'primitiveCreateDisplaySurface' module: 'Squeak3DX'>
  8698.     ^nil! !
  8699.  
  8700. !B3DDisplayScreen methodsFor: 'primitives-display' stamp: 'ar 5/27/2000 17:18'!
  8701. primDestroyDisplaySurface: aHandle
  8702.     "Primitive. Destroy the display surface associated with the given handle."
  8703.     <primitive: 'primitiveDestroyDisplaySurface' module:'Squeak3DX'>
  8704.     ^nil! !
  8705.  
  8706. !B3DDisplayScreen methodsFor: 'primitives-display' stamp: 'ar 5/27/2000 17:19'!
  8707. primDisplay: aHandle colorMasksInto: anArray
  8708.     "Primitive. Store the bit masks for each color into the given array."
  8709.     <primitive: 'primitiveDisplayGetColorMasks' module:'Squeak3DX'>
  8710.     ^nil! !
  8711.  
  8712. !B3DDisplayScreen methodsFor: 'primitives-display' stamp: 'ar 5/27/2000 17:19'!
  8713. primFill: handle color: pixelWord x: x y: y w: w h: h
  8714.     "Primitive. Perform an accelerated fill operation on the receiver."
  8715.     <primitive:'primitiveFillDisplaySurface' module:'Squeak3DX'>
  8716.     ^nil! !
  8717.  
  8718. !B3DDisplayScreen methodsFor: 'primitives-display' stamp: 'ar 5/27/2000 17:20'!
  8719. primFinish: aHandle
  8720.     "Primitive. Finish all rendering operations on the receiver.
  8721.     Do not return before all rendering operations have taken effect."
  8722.     <primitive: 'primitiveFinishDisplaySurface' module:'Squeak3DX'>
  8723.     ^nil! !
  8724.  
  8725. !B3DDisplayScreen methodsFor: 'primitives-display' stamp: 'ar 5/27/2000 17:21'!
  8726. primFlush: aHandle
  8727.     "Primitive. If any rendering operations are pending, force them to be executed.
  8728.     Do not wait until they have taken effect."
  8729.     <primitive: 'primitiveFlushDisplaySurface' module:'Squeak3DX'>
  8730.     ^nil! !
  8731.  
  8732. !B3DDisplayScreen methodsFor: 'primitives-display' stamp: 'ar 5/27/2000 17:21'!
  8733. supportsDisplayDepth: pixelDepth
  8734.     "Return true if this pixel depth is supported on the current host platform."
  8735.     <primitive: 'primitiveSupportsDisplayDepth' module:'Squeak3DX'>
  8736.     ^false! !
  8737.  
  8738. !B3DDisplayScreen methodsFor: 'primitives-forms' stamp: 'ar 5/27/2000 17:21'!
  8739. primAllocateForm: d width: w height: h
  8740.     "Primitive. Allocate a form with the given parameters"
  8741.     <primitive:'primitiveAllocateForm' module:'Squeak3DX'>
  8742.     ^nil! !
  8743.  
  8744. !B3DDisplayScreen methodsFor: 'primitives-forms' stamp: 'ar 5/27/2000 17:22'!
  8745. primDestroyForm: aHandle
  8746.     "Primitive. Destroy the form associated with the given handle."
  8747.     <primitive:'primitiveDestroyForm' module:'Squeak3DX'>
  8748.     ^nil! !
  8749.  
  8750. !B3DDisplayScreen methodsFor: 'primitives-forms' stamp: 'ar 5/27/2000 17:22'!
  8751. primForm: aHandle colorMasksInto: anArray
  8752.     "Primitive. Store the bit masks for each color into the given array."
  8753.     <primitive: 'primitiveFormGetColorMasks' module:'Squeak3DX'>
  8754.     ^nil! !
  8755.  
  8756. !B3DDisplayScreen methodsFor: 'primitives-textures' stamp: 'ar 5/27/2000 20:21'!
  8757. primAllocateTexture: d width: w height: h
  8758.     "Primitive. Allocate a texture with the given dimensions.
  8759.     Note: The texture allocated may *not* match the specified values here."
  8760.     <primitive:'primitiveAllocateTexture' module:'Squeak3DX'>
  8761.     ^nil! !
  8762.  
  8763. !B3DDisplayScreen methodsFor: 'primitives-textures' stamp: 'ar 5/27/2000 17:23'!
  8764. primDestroyTexture: aHandle
  8765.     "Primitive. Destroy the texture associated with the given handle."
  8766.     <primitive:'primitiveDestroyTexture' module:'Squeak3DX'>
  8767.     ^nil! !
  8768.  
  8769. !B3DDisplayScreen methodsFor: 'primitives-textures' stamp: 'ar 5/27/2000 17:23'!
  8770. primGetTextureDepth: aHandle
  8771.     "Primitive. Return the actual depth of the texture with the given handle"
  8772.     <primitive:'primitiveTextureDepth' module:'Squeak3DX'>
  8773.     ^self primitiveFailed! !
  8774.  
  8775. !B3DDisplayScreen methodsFor: 'primitives-textures' stamp: 'ar 5/27/2000 17:24'!
  8776. primGetTextureHeight: aHandle
  8777.     "Primitive. Return the actual height of the texture with the given handle"
  8778.     <primitive:'primitiveTextureHeight' module:'Squeak3DX'>
  8779.     ^self primitiveFailed! !
  8780.  
  8781. !B3DDisplayScreen methodsFor: 'primitives-textures' stamp: 'ar 5/27/2000 17:24'!
  8782. primGetTextureWidth: aHandle
  8783.     "Primitive. Return the actual width of the texture with the given handle"
  8784.     <primitive:'primitiveTextureWidth' module:'Squeak3DX'>
  8785.     ^self primitiveFailed! !
  8786.  
  8787. !B3DDisplayScreen methodsFor: 'primitives-textures' stamp: 'ar 5/27/2000 17:24'!
  8788. primTexture: aHandle colorMasksInto: anArray
  8789.     "Primitive. Store the bit masks for each color into the given array."
  8790.     <primitive: 'primitiveTextureGetColorMasks' module:'Squeak3DX'>
  8791.     ^nil! !
  8792.  
  8793. I am the superclass for all separate parts of the Balloon 3D engine. I define the basic interface each part of the engine must respond to.
  8794.  
  8795. Instance variables:
  8796.     engine    <B3DRenderEngine>    The 3D engine I am associated with!
  8797. !B3DEnginePart methodsFor: 'initialize' stamp: 'ar 2/16/1999 01:47'!
  8798. destroy
  8799.     "Destroy all resources temporarily assigned to the receiver"! !
  8800.  
  8801. !B3DEnginePart methodsFor: 'initialize' stamp: 'ar 2/5/1999 21:34'!
  8802. flush
  8803.     "Flush all pending operations"! !
  8804.  
  8805. !B3DEnginePart methodsFor: 'initialize'!
  8806. initialize
  8807. ! !
  8808.  
  8809. !B3DEnginePart methodsFor: 'initialize' stamp: 'ar 4/10/1999 22:52'!
  8810. reset
  8811. ! !
  8812.  
  8813. !B3DEnginePart methodsFor: 'private'!
  8814. setEngine: aB3DRenderEngine
  8815.     engine _ aB3DRenderEngine! !
  8816.  
  8817. !B3DEnginePart methodsFor: 'processing' stamp: 'ar 2/7/1999 03:39'!
  8818. processIndexedLines: vb
  8819.     "Process an indexed line set"! !
  8820.  
  8821. !B3DEnginePart methodsFor: 'processing' stamp: 'ar 2/8/1999 15:36'!
  8822. processIndexedQuads: vb
  8823.     "Process an indexed quad set"! !
  8824.  
  8825. !B3DEnginePart methodsFor: 'processing' stamp: 'ar 2/7/1999 03:39'!
  8826. processIndexedTriangles: vb
  8827.     "Process an indexed triangle set"! !
  8828.  
  8829. !B3DEnginePart methodsFor: 'processing' stamp: 'ar 2/4/1999 04:21'!
  8830. processLineLoop: vertexBuffer
  8831.     "Process a closed line defined by the vertex buffer"! !
  8832.  
  8833. !B3DEnginePart methodsFor: 'processing' stamp: 'ar 2/4/1999 04:21'!
  8834. processLines: vertexBuffer
  8835.     "Process a series of lines defined by each two points the vertex buffer"! !
  8836.  
  8837. !B3DEnginePart methodsFor: 'processing' stamp: 'ar 2/4/1999 04:21'!
  8838. processPoints: vertexBuffer
  8839.     "Process a series of points defined by the vertex buffer"! !
  8840.  
  8841. !B3DEnginePart methodsFor: 'processing' stamp: 'ar 2/4/1999 04:22'!
  8842. processPolygon: vertexBuffer
  8843.     "Process a polygon defined by the vertex buffer"! !
  8844.  
  8845. !B3DEnginePart methodsFor: 'processing' stamp: 'ar 2/8/1999 15:35'!
  8846. processVertexBuffer: vb
  8847.     "Process the given vertex buffer in this part of the engine."
  8848.     ^self perform: (PrimitiveActions at: vb primitive) with: vb! !
  8849.  
  8850. !B3DEnginePart class methodsFor: 'instance creation'!
  8851. engine: aB3DRenderEngine
  8852.     ^self new setEngine: aB3DRenderEngine! !
  8853.  
  8854. !B3DEnginePart class methodsFor: 'instance creation'!
  8855. new
  8856.     ^super new initialize! !
  8857.  
  8858. !B3DEnginePart class methodsFor: 'class initialization' stamp: 'ar 2/7/1999 19:52'!
  8859. initialize
  8860.     "B3DEnginePart initialize"
  8861.     PrimitiveActions _ 
  8862.         #(    processPoints:
  8863.             processLines:
  8864.             processPolygon:
  8865.             processIndexedLines:
  8866.             processIndexedTriangles:
  8867.             processIndexedQuads:
  8868.         ).! !
  8869.  
  8870. !B3DEnginePart class methodsFor: 'testing' stamp: 'ar 2/14/1999 01:39'!
  8871. isAvailable
  8872.     "Return true if this part of the engine is available"
  8873.     ^self subclassResponsibility! !
  8874.  
  8875. !B3DEnginePart class methodsFor: 'testing' stamp: 'ar 2/17/1999 04:39'!
  8876. isAvailableFor: anOutputMedium
  8877.     "Return true if this part of the engine is available for the given output medium"
  8878.     ^self isAvailable! !
  8879.  
  8880. I am a generic superclass for all Balloon 3D plugins.!
  8881. !B3DEnginePlugin methodsFor: 'primitive support' stamp: 'ar 2/14/1999 00:01'!
  8882. stackMatrix: index
  8883.     "Load a 4x4 transformation matrix from the interpreter stack.
  8884.     Return a pointer to the matrix data if successful, nil otherwise."
  8885.     | oop |
  8886.     self inline: false.
  8887.     self returnTypeC:'void*'.
  8888.     oop _ interpreterProxy stackObjectValue: index.
  8889.     oop = nil ifTrue:[^nil].
  8890.     ((interpreterProxy isWords: oop) and:[(interpreterProxy slotSizeOf: oop) = 16])
  8891.         ifTrue:[^interpreterProxy firstIndexableField: oop].
  8892.     ^nil! !
  8893.  
  8894. !B3DEnginePlugin methodsFor: 'primitive support' stamp: 'ar 4/12/1999 02:15'!
  8895. stackPrimitiveIndexArray: stackIndex ofSize: nItems validate: aBool forVertexSize: maxIndex
  8896.     "Load a primitive index array from the interpreter stack.
  8897.     If aBool is true then check that all the indexes are in the range (1,maxIndex).
  8898.     Return a pointer to the index data if successful, nil otherwise."
  8899.     | oop oopSize idxPtr index |
  8900.     self inline: false.
  8901.     self returnTypeC:'void*'.
  8902.     self var: #idxPtr declareC:'int *idxPtr'.
  8903.  
  8904.     oop _ interpreterProxy stackObjectValue: stackIndex.
  8905.     oop = nil ifTrue:[^nil].
  8906.     (interpreterProxy isWords: oop) ifFalse:[^nil].
  8907.      oopSize _ interpreterProxy slotSizeOf: oop.
  8908.     oopSize < nItems ifTrue:[^nil].
  8909.     idxPtr _ self cCoerce: (interpreterProxy firstIndexableField: oop) to:'int *'.
  8910.     aBool ifTrue:[
  8911.         0 to: nItems-1 do:[:i|
  8912.             index _ idxPtr at: i.
  8913.             (index < 0 or:[index > maxIndex]) ifTrue:[^nil]]].
  8914.     ^idxPtr! !
  8915.  
  8916. !B3DEnginePlugin methodsFor: 'primitive support' stamp: 'ar 2/14/1999 00:00'!
  8917. stackPrimitiveVertex: index
  8918.     "Load a primitive vertex from the interpreter stack.
  8919.     Return a pointer to the vertex data if successful, nil otherwise."
  8920.     | oop |
  8921.     self inline: false.
  8922.     self returnTypeC:'void*'.
  8923.     oop _ interpreterProxy stackObjectValue: index.
  8924.     oop = nil ifTrue:[^nil].
  8925.     ((interpreterProxy isWords: oop) and:[(interpreterProxy slotSizeOf: oop) = PrimVertexSize])
  8926.         ifTrue:[^interpreterProxy firstIndexableField: oop].
  8927.     ^nil! !
  8928.  
  8929. !B3DEnginePlugin methodsFor: 'primitive support' stamp: 'ar 2/14/1999 00:00'!
  8930. stackPrimitiveVertexArray: index ofSize: nItems
  8931.     "Load a primitive vertex array from the interpreter stack.
  8932.     Return a pointer to the vertex data if successful, nil otherwise."
  8933.     | oop oopSize |
  8934.     self inline: false.
  8935.     self returnTypeC:'void*'.
  8936.     oop _ interpreterProxy stackObjectValue: index.
  8937.     oop = nil ifTrue:[^nil].
  8938.     (interpreterProxy isWords: oop) ifTrue:[
  8939.          oopSize _ interpreterProxy slotSizeOf: oop.
  8940.         (oopSize >= nItems * PrimVertexSize and:[oopSize \\ PrimVertexSize = 0])
  8941.             ifTrue:[^interpreterProxy firstIndexableField: oop]].
  8942.     ^nil! !
  8943.  
  8944. !B3DEnginePlugin methodsFor: 'initialize-release' stamp: 'ar 5/16/2000 20:05'!
  8945. initialiseModule
  8946.     self export: true.
  8947.     loadBBFn _ interpreterProxy ioLoadFunction: 'loadBitBltFrom' From: bbPluginName.
  8948.     copyBitsFn _ interpreterProxy ioLoadFunction: 'copyBitsFromtoat' From: bbPluginName.
  8949.     ^(loadBBFn ~= 0 and:[copyBitsFn ~= 0])! !
  8950.  
  8951. !B3DEnginePlugin methodsFor: 'initialize-release' stamp: 'ar 5/16/2000 20:05'!
  8952. moduleUnloaded: aModuleName
  8953.     "The module with the given name was just unloaded.
  8954.     Make sure we have no dangling references."
  8955.     self export: true.
  8956.     self var: #aModuleName type: 'char *'.
  8957.     (aModuleName strcmp: bbPluginName) = 0 ifTrue:[
  8958.         "BitBlt just shut down. How nasty."
  8959.         loadBBFn _ 0.
  8960.         copyBitsFn _ 0.
  8961.     ].! !
  8962.  
  8963. !B3DEnginePlugin class methodsFor: 'translation' stamp: 'ar 5/16/2000 20:05'!
  8964. declareCVarsIn: cg
  8965.     cg var: 'bbPluginName' declareC:'char bbPluginName[256] = "BitBltPlugin"'.! !
  8966.  
  8967. !B3DEnginePlugin class methodsFor: 'translation' stamp: 'ar 2/8/1999 20:48'!
  8968. moduleName
  8969.     ^'Squeak3D'! !
  8970.  
  8971. !B3DEnginePlugin class methodsFor: 'translation' stamp: 'TPR 5/23/2000 17:26'!
  8972. translate: fileName doInlining: inlineFlag locally: localFlag
  8973.     "Time millisecondsToRun: [
  8974.         FloatArrayPlugin translate: 'SqFloatArray.c' doInlining: true.
  8975.         Smalltalk beep]"
  8976.     | cg fullName fd |
  8977.     fullName _ self baseDirectoryName.
  8978.     fd _ FileDirectory on: fullName.
  8979.     localFlag ifFalse:[
  8980.         (fd directoryExists: self moduleName) 
  8981.             ifFalse:[fd createDirectory: self moduleName].
  8982.         fd _ fd on: (fd fullNameFor: self moduleName)].
  8983.     fullName _ fd fullNameFor: fileName.
  8984.     self initialize.
  8985.     self headerFile ifNotNil:[
  8986.         (CrLfFileStream newFileNamed: (fd fullNameFor: self moduleName,'.h'))
  8987.             nextPutAll: self headerFile;
  8988.             close].
  8989.     cg _ self codeGeneratorClass new initialize.
  8990.     localFlag ifTrue:[cg pluginPrefix: self moduleName].
  8991.     "Add an extra declaration for module name"
  8992.         cg declareModuleName: self moduleNameAndVersion local: localFlag.
  8993.  
  8994.  
  8995.     {InterpreterPlugin. B3DEnginePlugin. B3DTransformerPlugin. B3DVertexBufferPlugin. B3DShaderPlugin. B3DClipperPlugin. B3DPickerPlugin. B3DRasterizerPlugin} do: 
  8996.         [:theClass | 
  8997.         theClass initialize.
  8998.         cg addClass: theClass.
  8999.         theClass declareCVarsIn: cg].
  9000.     cg storeCodeOnFile: fullName doInlining: inlineFlag.
  9001.     B3DRasterizerPlugin writeSupportCode: true.
  9002.     ^cg! !
  9003.  
  9004. !B3DEnginePlugin class methodsFor: 'translation' stamp: 'TPR 5/23/2000 17:26'!
  9005. translateB3D
  9006.     "B3DEnginePlugin translateB3D"
  9007.     "Translate all the basic plugins into one support module 
  9008.     and write the C sources for the rasterizer."
  9009.     | cg |
  9010.     cg _ PluggableCodeGenerator new initialize.
  9011.         cg declareModuleName: self moduleNameAndVersion local: false.
  9012.  
  9013.     {InterpreterPlugin. B3DEnginePlugin. B3DTransformerPlugin. B3DVertexBufferPlugin. B3DShaderPlugin. B3DClipperPlugin. B3DPickerPlugin. B3DRasterizerPlugin} do: 
  9014.         [:theClass | 
  9015.         theClass initialize.
  9016.         cg addClass: theClass.
  9017.         theClass declareCVarsIn: cg].
  9018.     cg storeCodeOnFile: self moduleName , '.c' doInlining: true.
  9019.     "    cg storeCodeOnFile: '/tmp/Ballon3D.c' doInlining: true."
  9020.     B3DRasterizerPlugin writeSupportCode: true! !
  9021.  
  9022. I represent a lookup table for several exponents during lighting. Values are computed based on linear interpolation between the stored elements. New tables are created by providing a one argument initialization block from  which I am created.!
  9023. !B3DExponentTable methodsFor: 'initialize' stamp: 'ar 2/8/1999 00:08'!
  9024. initializeFrom: aBlock
  9025.     | last next |
  9026.     last _ nil.
  9027.     1 to: self size // 2 do:[:i|
  9028.         next _ aBlock value: (i-1) / (self size // 2 - 1) asFloat.
  9029.         (next isInfinite or:[next isNaN]) ifTrue:[next _ 0.0].
  9030.         self at: i*2-1 put: next.
  9031.         i > 1 ifTrue:[self at: i-1*2 put: next - last].
  9032.         last _ next.
  9033.     ].! !
  9034.  
  9035. !B3DExponentTable methodsFor: 'accessing' stamp: 'ar 2/8/1999 00:10'!
  9036. valueAt: aFloat
  9037.     "Return the table approximation for the given float value"
  9038.     | index max |
  9039.     aFloat < 0.0 ifTrue:[^self error:'Cannot use negative numbers in table lookup'].
  9040.     max _ self size // 2.
  9041.     index _ (max * aFloat) asInteger + 1.
  9042.     index >= max ifTrue:[^self at: self size-1].
  9043.     "Linear interpolation inbetween"
  9044.     ^(self at: index) + (aFloat - (index-1) * (self at: index+1))! !
  9045.  
  9046. !B3DExponentTable class methodsFor: 'class initialization' stamp: 'ar 2/8/1999 00:02'!
  9047. initialize
  9048.     "B3DExponentTable initialize"
  9049.     DefaultExponents _ Dictionary new.
  9050.     0 to: 2 do:[:i|
  9051.         DefaultExponents at: i put: (self using:[:value| value raisedTo: i]).
  9052.     ].! !
  9053.  
  9054. !B3DExponentTable class methodsFor: 'instance creation' stamp: 'ar 2/7/1999 23:56'!
  9055. new
  9056.     ^self using:[:value| value]! !
  9057.  
  9058. !B3DExponentTable class methodsFor: 'instance creation' stamp: 'ar 2/7/1999 23:55'!
  9059. numElements
  9060.     ^128! !
  9061.  
  9062. !B3DExponentTable class methodsFor: 'instance creation' stamp: 'ar 2/7/1999 23:59'!
  9063. using: aBlock
  9064.     "Create a new exponent table using aBlock as initialization"
  9065.     ^super new initializeFrom: aBlock! !
  9066.  
  9067. !B3DFillList methodsFor: 'initialize' stamp: 'ar 4/4/1999 04:28'!
  9068. initialize
  9069.     self reset.! !
  9070.  
  9071. !B3DFillList methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:39'!
  9072. first
  9073.     ^firstFace! !
  9074.  
  9075. !B3DFillList methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:49'!
  9076. last
  9077.     ^lastFace! !
  9078.  
  9079. !B3DFillList methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:31'!
  9080. reset
  9081.     firstFace _ lastFace _ nil.! !
  9082.  
  9083. !B3DFillList methodsFor: 'accessing' stamp: 'ar 4/18/1999 06:00'!
  9084. searchForNewTopAtX: xValue y: yValue
  9085.     "A top face ended with no known right face.
  9086.     We have to search the fill list for the face with the smallest z value.
  9087.     Note: In theory, this should only happen on *right* boundaries of meshes
  9088.     and thus not affect performance too much. Having the fillList sorted by
  9089.     its minimal z value should help, too."
  9090.     | face topFace topZ faceZ floatX floatY |
  9091.     self isEmpty ifTrue:[^self]. "No top"
  9092.     floatX _ xValue / 4096.0.
  9093.     floatY _ yValue.
  9094.     face _ self first.
  9095.     topFace _ face.
  9096.     topZ _ face zValueAtX: floatX y: floatY.
  9097.     [face _ face nextFace.
  9098.     face == nil] whileFalse:[
  9099.         face minZ > topZ ifTrue:[
  9100.             "Done. Everything else is behind."
  9101.             self remove: topFace.
  9102.             self addFront: topFace.
  9103.             ^self].
  9104.         faceZ _ face zValueAtX: floatX y: floatY.
  9105.         faceZ < topZ ifTrue:[
  9106.             topZ _ faceZ.
  9107.             topFace _ face]].
  9108.     self remove: topFace.
  9109.     self addFront: topFace.! !
  9110.  
  9111. !B3DFillList methodsFor: 'accessing' stamp: 'ar 4/4/1999 23:53'!
  9112. size
  9113.     | n face |
  9114.     n _ 0.
  9115.     face _ firstFace.
  9116.     [face == nil] whileFalse:[
  9117.         n _ n + 1.
  9118.         face _ face nextFace.
  9119.     ].
  9120.     ^n! !
  9121.  
  9122. !B3DFillList methodsFor: 'adding' stamp: 'ar 4/5/1999 20:38'!
  9123. addBack: aFace
  9124.     "Add the given face as a non-front face (e.g., insert it after the front face).
  9125.     Make sure that the receiver stays sorted by the minimal z values of faces."
  9126.     | minZ midZ face |
  9127.     firstFace == nil ifTrue:[^self error:'Inserting a back face with no front face'].
  9128.     minZ _ aFace minZ.
  9129.     "Quick optimization for insertion at end"
  9130.     (firstFace == lastFace or:[minZ >= lastFace minZ]) ifTrue:[^self addLast: aFace].
  9131.     "Try an estimation for how to search"
  9132.     midZ _ (firstFace nextFace minZ + lastFace minZ) * 0.5.
  9133.     minZ <= midZ ifTrue:[
  9134.         "Search front to back"
  9135.         face _ firstFace nextFace.
  9136.         [face minZ < minZ] whileTrue:[face _ face nextFace].
  9137.     ] ifFalse:[
  9138.         "Search back to front"
  9139.         face _ lastFace prevFace. "Already checked for lastFace minZ < face minZ"
  9140.         [face minZ > minZ] whileTrue:[face _ face prevFace].
  9141.         face _ face nextFace.
  9142.     ].
  9143.     self insert: aFace before: face.! !
  9144.  
  9145. !B3DFillList methodsFor: 'adding' stamp: 'ar 4/18/1999 08:04'!
  9146. addFirst: aFace
  9147.     firstFace isNil
  9148.         ifTrue:[lastFace _ aFace]
  9149.         ifFalse:[firstFace prevFace: aFace].
  9150.     aFace nextFace: firstFace.
  9151.     aFace prevFace: nil.
  9152.     firstFace _ aFace.
  9153.     B3DScanner doDebug ifTrue:[self validate].! !
  9154.  
  9155. !B3DFillList methodsFor: 'adding' stamp: 'ar 4/5/1999 20:41'!
  9156. addFront: aFace
  9157.     "Add the given face as the new front face.
  9158.     Make sure the sort order stays okay."
  9159.     | backFace minZ tempFace |
  9160.     firstFace == lastFace ifFalse:["firstFace == lastFace denotes 0 or 1 elements"
  9161.         backFace _ firstFace nextFace.
  9162.         minZ _ firstFace minZ.
  9163.         [backFace notNil and:[backFace minZ < minZ]] 
  9164.             whileTrue:[backFace _ backFace nextFace].
  9165.         "backFace contains the face before which firstFace has to be added"
  9166.         firstFace nextFace == backFace ifFalse:[
  9167.             tempFace _ firstFace.
  9168.             self remove: tempFace.
  9169.             backFace == nil 
  9170.                 ifTrue:[self addLast: tempFace]
  9171.                 ifFalse:[self insert: tempFace before: backFace].
  9172.         ].
  9173.     ].
  9174.     ^self addFirst: aFace! !
  9175.  
  9176. !B3DFillList methodsFor: 'adding' stamp: 'ar 4/18/1999 08:04'!
  9177. addLast: aFace
  9178.     lastFace isNil
  9179.         ifTrue:[firstFace _ aFace]
  9180.         ifFalse:[lastFace nextFace: aFace].
  9181.     aFace prevFace: lastFace.
  9182.     aFace nextFace: nil.
  9183.     lastFace _ aFace.
  9184.     B3DScanner doDebug ifTrue:[self validate].! !
  9185.  
  9186. !B3DFillList methodsFor: 'adding' stamp: 'ar 4/18/1999 08:04'!
  9187. insert: aFace before: nextFace
  9188.     "Insert the given face before nextFace."
  9189.     B3DScanner doDebug ifTrue:[
  9190.         (self includes: nextFace) ifFalse:[^self error:'Face not in collection'].
  9191.         (self includes: aFace) ifTrue:[^self error:'Face already in collection'].
  9192.     ].
  9193.     aFace nextFace: nextFace.
  9194.     aFace prevFace: nextFace prevFace.
  9195.     aFace prevFace nextFace: aFace.
  9196.     nextFace prevFace: aFace.
  9197.     B3DScanner doDebug ifTrue:[self validate].! !
  9198.  
  9199. !B3DFillList methodsFor: 'removing' stamp: 'ar 4/18/1999 08:04'!
  9200. remove: aFace
  9201.     (B3DScanner doDebug and:[(self includes: aFace) not]) 
  9202.         ifTrue:[^self error:'Face not in list'].
  9203.     B3DScanner doDebug ifTrue:[self validate].
  9204.     aFace prevFace isNil
  9205.         ifTrue:[firstFace _ aFace nextFace]
  9206.         ifFalse:[aFace prevFace nextFace: aFace nextFace].
  9207.     aFace nextFace isNil
  9208.         ifTrue:[lastFace _ aFace prevFace]
  9209.         ifFalse:[aFace nextFace prevFace: aFace prevFace].
  9210.     ^aFace! !
  9211.  
  9212. !B3DFillList methodsFor: 'enumerating' stamp: 'ar 4/18/1999 08:03'!
  9213. do: aBlock
  9214.     | face |
  9215.     B3DScanner doDebug ifTrue:[self validate].
  9216.     face _ firstFace.
  9217.     [face == nil] whileFalse:[
  9218.         aBlock value: face.
  9219.         face _ face nextFace.
  9220.     ].! !
  9221.  
  9222. !B3DFillList methodsFor: 'testing' stamp: 'ar 4/5/1999 01:58'!
  9223. includes: aFace
  9224.     | face |
  9225.     face _ firstFace.
  9226.     [face == nil] whileFalse:[
  9227.         face == aFace ifTrue:[^true].
  9228.         face _ face nextFace.
  9229.     ].
  9230.     ^false! !
  9231.  
  9232. !B3DFillList methodsFor: 'testing' stamp: 'ar 4/3/1999 00:49'!
  9233. isEmpty
  9234.     ^firstFace == nil! !
  9235.  
  9236. !B3DFillList methodsFor: 'private' stamp: 'ar 4/5/1999 03:54'!
  9237. printOn: aStream
  9238.     super printOn: aStream.
  9239.     aStream
  9240.         nextPut:$(;
  9241.         print: self size;
  9242.         nextPut: $).! !
  9243.  
  9244. !B3DFillList methodsFor: 'private' stamp: 'ar 4/5/1999 20:27'!
  9245. validate
  9246.     | face |
  9247.     (firstFace == nil and:[lastFace == nil]) ifTrue:[^self].
  9248.     firstFace prevFace == nil ifFalse:[^self error:'Bad list'].
  9249.     lastFace nextFace == nil ifFalse:[^self error:'Bad list'].
  9250.     face _ firstFace.
  9251.     [face == lastFace] whileFalse:[face _ face nextFace].
  9252.     self validateSortOrder.! !
  9253.  
  9254. !B3DFillList methodsFor: 'private' stamp: 'ar 4/5/1999 20:39'!
  9255. validateSortOrder
  9256.     | backFace |
  9257.     firstFace == lastFace ifTrue:[^self]. "0 or 1 element"
  9258.     backFace _ firstFace nextFace.
  9259.     [backFace nextFace == nil] whileFalse:[
  9260.         backFace minZ <= backFace nextFace minZ ifFalse:[^self error:'Sorting error'].
  9261.         backFace _ backFace nextFace.
  9262.     ].! !
  9263.  
  9264. !B3DFillList class methodsFor: 'instance creation' stamp: 'ar 4/4/1999 04:27'!
  9265. new
  9266.     ^super new initialize! !
  9267.  
  9268. I am the superclass for all Balloon 3D vector objects.!
  9269. !B3DFloatArray methodsFor: 'accessing'!
  9270. floatAt: index
  9271.     "For subclasses that override #at:"
  9272.     <primitive: 'primitiveFloatArrayAt'>
  9273.     ^Float fromIEEE32Bit: (self basicAt: index)! !
  9274.  
  9275. !B3DFloatArray methodsFor: 'accessing'!
  9276. floatAt: index put: value
  9277.     "For subclasses that override #at:put:"
  9278.     <primitive: 'primitiveFloatArrayAtPut'>
  9279.     self basicAt: index put: value asIEEE32BitWord.
  9280.     ^value! !
  9281.  
  9282. !B3DFloatArray methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:23'!
  9283. numElements
  9284.     ^self class numElements! !
  9285.  
  9286. !B3DFloatArray methodsFor: 'accessing' stamp: 'ar 2/15/1999 22:10'!
  9287. wordAt: index
  9288.     <primitive: 60>
  9289.     ^self primitiveFailed! !
  9290.  
  9291. !B3DFloatArray methodsFor: 'accessing' stamp: 'ar 2/15/1999 22:10'!
  9292. wordAt: index put: value
  9293.     <primitive: 61>
  9294.     ^self primitiveFailed! !
  9295.  
  9296. !B3DFloatArray methodsFor: 'initialize'!
  9297. loadFrom: srcObject
  9298.     self == srcObject ifTrue:[^self].
  9299.     self class == srcObject class
  9300.         ifTrue:[self replaceFrom: 1 to: self size with: srcObject startingAt: 1]
  9301.         ifFalse:[self privateLoadFrom: srcObject]! !
  9302.  
  9303. !B3DFloatArray methodsFor: 'private'!
  9304. privateLoadFrom: srcObject
  9305.     "Load the receiver from the given source object."
  9306.     self error:'Cannot load a ', srcObject class name,' into a ', self class name.! !
  9307.  
  9308. !B3DFloatArray class methodsFor: 'instance creation' stamp: 'ar 2/1/1999 21:20'!
  9309. new
  9310.     ^super new: self numElements! !
  9311.  
  9312. !B3DFloatArray class methodsFor: 'instance creation' stamp: 'ar 2/1/1999 21:21'!
  9313. numElements
  9314.     ^0! !
  9315.  
  9316. B3DHardwareEngine is a render engine specifically designed to deal with HW accellerated implementations. The (currently only) difference to the generic render engine is that a HW accellerated engine automatically clips the virtual viewport specified by client. This is necessary since HW accellerated rasterizers can usually not render outside the actual display surface.
  9317.  
  9318. Note: If the viewport clipping proves to be efficient enough it might be promoted to the general render engine since there is no point in rendering outside the clipping rectangle.!
  9319. !B3DHardwareEngine methodsFor: 'accessing' stamp: 'ar 5/28/2000 04:05'!
  9320. viewport: aRectangle
  9321.     "check if we need a transform override for the viewport"
  9322.     | vp clipRect |
  9323.     vp _ aRectangle.
  9324.     clipRect _ rasterizer clipRect.
  9325.     (clipRect containsRect: vp) ifTrue:[
  9326.         "Good. The viewport is fully within the clip rect."
  9327.         vpTransform _ nil.
  9328.     ] ifFalse:[
  9329.         "We need a transform override here"
  9330.         vp _ clipRect intersect: vp.
  9331.         "Actual viewport is vp. Now scale from aRectangle into vp.
  9332.         This is equivalent to picking vp center with vp extent."
  9333.         vp area > 0 ifTrue:[
  9334.             vpTransform _ self pickingMatrixFor: aRectangle at: (vp origin + vp corner) * 0.5 extent: vp extent].
  9335.     ].
  9336.     "And set actual viewport"
  9337.     super viewport: vp.! !
  9338.  
  9339. !B3DHardwareEngine methodsFor: 'private-rendering' stamp: 'ar 2/27/2000 20:14'!
  9340. privateTransformVB: vb
  9341.     vpTransform 
  9342.         ifNil:[^transformer processVertexBuffer: vb]
  9343.         ifNotNil:["We must override the projection matrix here"
  9344.             ^transformer
  9345.                 processVertexBuffer: vb
  9346.                     modelView: transformer modelViewMatrix
  9347.                     projection: (transformer projectionMatrix composedWithGlobal: vpTransform)].! !
  9348.  
  9349. !B3DHardwareEngine class methodsFor: 'accessing' stamp: 'ar 2/24/2000 00:15'!
  9350. rasterizer
  9351.     ^B3DHardwareRasterizer! !
  9352.  
  9353. WICHTIG:
  9354.  
  9355.     Viewport muss an den renderer gebunden sein.
  9356.     Viewport kann multiple sein.
  9357. !
  9358. !B3DHardwareRasterizer methodsFor: 'initialize' stamp: 'ar 5/26/2000 15:13'!
  9359. finish
  9360.     "Wait until drawing was completed so we won't get into any trouble with 2D operations afterwards. Note: Later we will synchronize this with the portions of display in use."
  9361.     target finish! !
  9362.  
  9363. !B3DHardwareRasterizer methodsFor: 'initialize' stamp: 'ar 5/26/2000 15:13'!
  9364. flush
  9365.     "Flush the pipeline. Flushing will force processing but not wait until it's finished."
  9366.     target flush.! !
  9367.  
  9368. !B3DHardwareRasterizer methodsFor: 'initialize' stamp: 'ar 5/26/2000 15:28'!
  9369. viewport: vp
  9370.     super viewport: vp.
  9371.     self primSetViewportX: viewport left 
  9372.             y: viewport top 
  9373.             w: viewport width 
  9374.             h: viewport height.! !
  9375.  
  9376. !B3DHardwareRasterizer methodsFor: 'accessing' stamp: 'ar 5/27/2000 00:47'!
  9377. clearDepthBuffer
  9378.     self primClearDepthBuffer.! !
  9379.  
  9380. !B3DHardwareRasterizer methodsFor: 'testing' stamp: 'ar 2/24/2000 00:00'!
  9381. needsClip
  9382.     ^true! !
  9383.  
  9384. !B3DHardwareRasterizer methodsFor: 'processing' stamp: 'ar 5/27/2000 17:27'!
  9385. processVertexBuffer: vb
  9386.     self primProcessVB: vb primitive 
  9387.             texture: (target textureHandleOf: texture) 
  9388.             vertices: vb vertexArray 
  9389.             vertexCount: vb vertexCount 
  9390.             faces: vb indexArray 
  9391.             faceCount: vb indexCount.
  9392.     ^nil! !
  9393.  
  9394. !B3DHardwareRasterizer methodsFor: 'primitives' stamp: 'ar 5/26/2000 15:06'!
  9395. primClearDepthBuffer
  9396.     <primitive:'primitiveClearDepthBuffer' module:'Squeak3DX'>
  9397.     ^self primitiveFailed! !
  9398.  
  9399. !B3DHardwareRasterizer methodsFor: 'primitives' stamp: 'ar 5/26/2000 12:49'!
  9400. primProcessVB: primitiveType texture: textureHandle vertices: vtxArray vertexCount: vtxCount faces: idxArray faceCount: idxCount
  9401.     <primitive:'primitiveProcessVertexBuffer' module:'Squeak3DX'>
  9402.     ^self primitiveFailed! !
  9403.  
  9404. !B3DHardwareRasterizer methodsFor: 'primitives' stamp: 'ar 2/24/2000 00:06'!
  9405. primSetViewportX: left y: top w: width h: height
  9406.     <primitive:'primitiveSetViewport' module:'Squeak3DX'>
  9407.     ^self primitiveFailed! !
  9408.  
  9409. !B3DHardwareRasterizer class methodsFor: 'accessing' stamp: 'ar 5/25/2000 22:00'!
  9410. isAvailable
  9411.     ^self version > 0! !
  9412.  
  9413. !B3DHardwareRasterizer class methodsFor: 'accessing' stamp: 'ar 5/25/2000 22:01'!
  9414. version
  9415.     "B3DPrimitiveRasterizer version"
  9416.     <primitive:'primitiveRasterizerVersion' module:'Squeak3DX'>
  9417.     ^0! !
  9418.  
  9419. !B3DHardwareRasterizer class methodsFor: 'testing' stamp: 'ar 5/28/2000 15:04'!
  9420. isAvailableFor: aForm
  9421.     "Return true if this part of the engine is available for the given output medium"
  9422.     aForm ifNil:[^false].
  9423.     (aForm isDisplayScreen and:[aForm isB3DDisplayScreen]) ifFalse:[^false].
  9424.     ^self isAvailable! !
  9425.  
  9426. I represent a generic indexed face mesh. My subclasses define what kind of primitive objects I can represent. !
  9427. !B3DIndexedMesh methodsFor: 'accessing' stamp: 'ar 2/16/1999 19:08'!
  9428. boundingBox
  9429.     ^bBox ifNil:[bBox _ self computeBoundingBox]! !
  9430.  
  9431. !B3DIndexedMesh methodsFor: 'accessing' stamp: 'ar 2/16/1999 19:08'!
  9432. faceNormals
  9433.     ^faceNormals ifNil:[faceNormals _ self computeFaceNormals]! !
  9434.  
  9435. !B3DIndexedMesh methodsFor: 'accessing' stamp: 'ar 2/16/1999 19:08'!
  9436. faces
  9437.     ^faces! !
  9438.  
  9439. !B3DIndexedMesh methodsFor: 'accessing' stamp: 'jsp 3/11/1999 11:44'!
  9440. faces: newFaces
  9441.     faces _ newFaces.
  9442. ! !
  9443.  
  9444. !B3DIndexedMesh methodsFor: 'accessing' stamp: 'ar 2/16/1999 19:08'!
  9445. texCoords
  9446.     ^vtxTexCoords! !
  9447.  
  9448. !B3DIndexedMesh methodsFor: 'accessing' stamp: 'jsp 3/11/1999 11:43'!
  9449. texCoords: newTexCoords
  9450.     vtxTexCoords _ newTexCoords.
  9451. ! !
  9452.  
  9453. !B3DIndexedMesh methodsFor: 'accessing' stamp: 'ar 9/16/1999 14:49'!
  9454. vertexColors
  9455.     ^vtxColors! !
  9456.  
  9457. !B3DIndexedMesh methodsFor: 'accessing' stamp: 'ar 9/16/1999 14:50'!
  9458. vertexColors: aB3DColor4Array
  9459.     vtxColors _ aB3DColor4Array! !
  9460.  
  9461. !B3DIndexedMesh methodsFor: 'accessing' stamp: 'ar 2/16/1999 19:08'!
  9462. vertexNormals
  9463.     ^vtxNormals ifNil:[vtxNormals _ self computeVertexNormals].! !
  9464.  
  9465. !B3DIndexedMesh methodsFor: 'accessing' stamp: 'jsp 3/11/1999 11:44'!
  9466. vertexNormals: newNormals
  9467.     vtxNormals _ newNormals.! !
  9468.  
  9469. !B3DIndexedMesh methodsFor: 'accessing' stamp: 'ar 2/16/1999 19:08'!
  9470. vertices
  9471.     ^vertices! !
  9472.  
  9473. !B3DIndexedMesh methodsFor: 'accessing' stamp: 'jsp 3/11/1999 11:43'!
  9474. vertices: newVertices
  9475.     vertices _ newVertices.! !
  9476.  
  9477. !B3DIndexedMesh methodsFor: 'modifying' stamp: 'ar 2/16/1999 19:08'!
  9478. centerAtZero
  9479.     self translateBy: (self boundingBox origin + self boundingBox corner * -0.5).! !
  9480.  
  9481. !B3DIndexedMesh methodsFor: 'modifying' stamp: 'jsp 9/17/1999 14:13'!
  9482. transformBy: aMatrix
  9483.     "Modify the mesh by transforming it using a matrix; this allows us to change the insertion point of the mesh"
  9484.  
  9485.     vertices do: [:vtx |     vtx privateLoadFrom: ((aMatrix composeWith:
  9486.                                         (B3DMatrix4x4 identity translation: vtx)) translation) ].
  9487.  
  9488.     bBox ifNotNil: [ self computeBoundingBox ].
  9489.     self computeVertexNormals.
  9490. ! !
  9491.  
  9492. !B3DIndexedMesh methodsFor: 'modifying' stamp: 'ar 2/16/1999 19:08'!
  9493. translateBy: amount
  9494.     vertices do:[:vtx| vtx += amount].
  9495.     bBox ifNotNil:[bBox _ bBox translateBy: amount].! !
  9496.  
  9497. !B3DIndexedMesh methodsFor: 'displaying' stamp: 'ar 2/16/1999 19:08'!
  9498. renderOn: aRenderer
  9499.     ^self subclassResponsibility! !
  9500.  
  9501. !B3DIndexedMesh methodsFor: 'private' stamp: 'ar 2/16/1999 19:08'!
  9502. computeBoundingBox
  9503.     | min max |
  9504.     min _ max _ nil.
  9505.     vertices do:[:vtx|
  9506.         min ifNil:[min _ vtx] ifNotNil:[min _ min min: vtx].
  9507.         max ifNil:[max _ vtx] ifNotNil:[max _ max max: vtx].
  9508.     ].
  9509.     ^Rectangle origin: min corner: max! !
  9510.  
  9511. !B3DIndexedMesh methodsFor: 'private' stamp: 'ar 2/16/1999 19:09'!
  9512. computeFaceNormals
  9513.     | out face v1 v2 v3 d1 d2 normal |
  9514.     out _ B3DVector3Array new: faces size.
  9515.     1 to: faces size do:[:i|
  9516.         face _ faces at: i.
  9517.         v1 _ vertices at: face p1Index.
  9518.         v2 _ vertices at: face p2Index.
  9519.         v3 _ vertices at: face p3Index.
  9520.         d1 _ v3 - v1.
  9521.         d2 _ v2 - v1.
  9522.         d1 safelyNormalize.
  9523.         d2 safelyNormalize.
  9524.         normal _ d1 cross: d2.
  9525.         out at: i put: normal safelyNormalize.
  9526.     ].
  9527.     ^out! !
  9528.  
  9529. !B3DIndexedMesh methodsFor: 'private' stamp: 'ar 2/16/1999 19:09'!
  9530. computeVertexNormals
  9531.     | temp normals face normal v1 v2 v3 out |
  9532.     temp _ Array new: vertices size.
  9533.     1 to: temp size do:[:i| temp at: i put: B3DVector4 new].
  9534.     normals _ self faceNormals. "Forces computation if necessary"
  9535.     1 to: faces size do:[:i|
  9536.         face _ faces at: i.
  9537.         normal _ (normals at: i) asB3DVector4.
  9538.         v1 _ face p1Index.
  9539.         v2 _ face p2Index.
  9540.         v3 _ face p3Index.
  9541.         (temp at: v1) += normal.
  9542.         (temp at: v2) += normal.
  9543.         (temp at: v3) += normal.
  9544.     ].
  9545.     out _ B3DVector3Array new: vertices size.
  9546.     1 to: out size do:[:i|
  9547.         out at: i put: (temp at: i) asB3DVector3 safelyNormalize.
  9548.     ].
  9549.     ^out! !
  9550.  
  9551. !B3DIndexedMesh methodsFor: 'optimizations' stamp: 'ar 2/8/1999 06:52'!
  9552. optimizeMeshLayout
  9553.     "Optimize the layout of the indexed mesh for primitive operations.
  9554.     Optimzed layouts include triangle/quad strips and fans and 
  9555.     will result in MUCH better performance during rendering.
  9556.     However, optimizations are generally time-consuming so
  9557.     you better don't call this method too often."
  9558.     ^self "Must be implemented in my subclasses"! !
  9559.  
  9560. !B3DIndexedMesh methodsFor: 'converting' stamp: 'ar 9/17/1999 12:37'!
  9561. asSimpleMesh
  9562.     "Convert the receiver into a very simple mesh representation"
  9563.     | simpleFaces oldFace newVtx newFace newVertices pos |
  9564.     simpleFaces _ WriteStream on: (Array new: faces size).
  9565.     newVertices _ WriteStream on: (Array new: 10).
  9566.     1 to: faces size do:[:i|
  9567.         oldFace _ faces at: i.
  9568.         newVertices reset.
  9569.         1 to: oldFace size do:[:j|
  9570.             pos _ oldFace at: j.
  9571.             newVtx _ B3DSimpleMeshVertex new.
  9572.             newVtx position: (vertices at: pos).
  9573.             vtxNormals == nil ifFalse:[newVtx normal: (vtxNormals at: pos)].
  9574.             vtxColors == nil ifFalse:[newVtx color: (vtxColors at: pos)].
  9575.             vtxTexCoords == nil ifFalse:[newVtx texCoord: (vtxTexCoords at: pos)].
  9576.             newVertices nextPut: newVtx].
  9577.         newFace _ B3DSimpleMeshFace withAll: newVertices contents.
  9578.         simpleFaces nextPut: newFace].
  9579.     ^B3DSimpleMesh withAll: simpleFaces contents! !
  9580.  
  9581. !B3DIndexedMesh methodsFor: 'testing' stamp: 'ar 9/16/1999 23:32'!
  9582. hasVertexColors
  9583.     ^vtxColors notNil! !
  9584.  
  9585. !B3DIndexedMesh class methodsFor: 'class initialization' stamp: 'ar 9/16/1999 23:02'!
  9586. flushVRMLCache
  9587.     "B3DIndexedMesh flushVRMLCache"
  9588.     VRML97BoxCache _
  9589.     VRML97ConeCache _
  9590.     VRMLCylCache _
  9591.     VRMLSphereCache _
  9592.     nil.! !
  9593.  
  9594. !B3DIndexedMesh class methodsFor: 'class initialization' stamp: 'ar 2/8/1999 06:55'!
  9595. initialize    "B3DIndexedMesh initialize"
  9596.     "Optimization flags: These flags are *hints* and may be ignored by the renderer."
  9597.     FlagStripStart _ 1.
  9598.     FlagFanStart _ 2.! !
  9599.  
  9600. !B3DIndexedMesh class methodsFor: 'examples' stamp: 'ar 2/8/1999 21:18'!
  9601. sampleRect
  9602.     ^self sampleRect: 10! !
  9603.  
  9604. !B3DIndexedMesh class methodsFor: 'examples' stamp: 'ar 2/8/1999 16:58'!
  9605. sampleRect: n
  9606.     ^self new sampleRect: n! !
  9607.  
  9608. !B3DIndexedMesh class methodsFor: 'vrml97 prototypes' stamp: 'ar 9/16/1999 22:12'!
  9609. vrml97Box
  9610.     "Return a mesh representing a VRML97 Box"
  9611.     ^VRML97BoxCache ifNil:[
  9612.         VRML97BoxCache _ (B3DSimpleMesh withAll: self vrmlCreateBoxFaces) asIndexedMesh]! !
  9613.  
  9614. !B3DIndexedMesh class methodsFor: 'vrml97 prototypes' stamp: 'ar 9/16/1999 22:15'!
  9615. vrml97Cone
  9616.     "Return a mesh representing a VRML97 Cone"
  9617.     ^self vrml97Cone: true bottom: true.! !
  9618.  
  9619. !B3DIndexedMesh class methodsFor: 'vrml97 prototypes' stamp: 'ar 9/16/1999 22:14'!
  9620. vrml97Cone: doSide bottom: doBottom
  9621.     "Return a mesh representing a VRML97 Cone"
  9622.     | idx |
  9623.     idx _ 0.
  9624.     doBottom ifTrue:[idx _ idx + 2].
  9625.     doSide ifTrue:[idx _ idx + 1].
  9626.     VRML97ConeCache == nil ifTrue:[
  9627.         VRML97ConeCache _ Array new: 3.
  9628.         1 to: 3 do:[:i|
  9629.             VRML97ConeCache at: i put:
  9630.                 (self 
  9631.                     vrmlCreateCone: (i anyMask: 1) 
  9632.                     bottom: (i anyMask: 2))]].
  9633.     ^VRML97ConeCache at: idx! !
  9634.  
  9635. !B3DIndexedMesh class methodsFor: 'vrml97 prototypes' stamp: 'ar 9/16/1999 22:15'!
  9636. vrml97Cylinder
  9637.     "Return a mesh representing a VRML97 Cylinder"
  9638.     ^self vrml97Cylinder: true bottom: true top: true.! !
  9639.  
  9640. !B3DIndexedMesh class methodsFor: 'vrml97 prototypes' stamp: 'ar 9/16/1999 22:14'!
  9641. vrml97Cylinder: doSide bottom: doBottom top: doTop
  9642.     "Return a mesh representing a VRML97 Cylinder"
  9643.     | idx |
  9644.     idx _ 0.
  9645.     doTop ifTrue:[idx _ idx + 4].
  9646.     doBottom ifTrue:[idx _ idx + 2].
  9647.     doSide ifTrue:[idx _ idx + 1].
  9648.     idx = 0 ifTrue:[^nil].
  9649.     VRMLCylCache == nil ifTrue:[
  9650.         VRMLCylCache _ Array new: 7.
  9651.         1 to: 7 do:[:i|
  9652.             VRMLCylCache at: i put:
  9653.                 (self 
  9654.                     vrmlCreateCylinder: (i anyMask: 1) 
  9655.                     bottom: (i anyMask: 2) 
  9656.                     top: (i anyMask: 4))]].
  9657.     ^VRMLCylCache at: idx! !
  9658.  
  9659. !B3DIndexedMesh class methodsFor: 'vrml97 prototypes' stamp: 'ar 9/16/1999 22:21'!
  9660. vrml97Sphere
  9661.     "Return a mesh representing a VRML97 Sphere"
  9662.     ^VRMLSphereCache ifNil:[
  9663.         VRMLSphereCache _ (B3DSimpleMesh withAll: self vrmlCreateSphereFaces) asIndexedMesh].! !
  9664.  
  9665. !B3DIndexedMesh class methodsFor: 'vrml support' stamp: 'ar 9/16/1999 22:07'!
  9666. vrmlCreateBottomFaces
  9667.     | face steps dir m lastVtx nextVtx faceList midVtx |
  9668.     steps _ self vrmlSteps.
  9669.     faceList _ WriteStream on: (Array new: steps).
  9670.     dir _ 0@0@1.
  9671.     m _ (B3DRotation angle: (360.0 / steps) axis: (0@-1@0)) asMatrix4x4.
  9672.     lastVtx _ B3DSimpleMeshVertex new.
  9673.     lastVtx position: 0@-1@1.
  9674.     lastVtx normal: 0@-1@0.
  9675.     lastVtx texCoord: 0.5@1.
  9676.     1 to: steps do:[:i|
  9677.         face _ B3DSimpleMeshFace new: 3.
  9678.         face at: 1 put: lastVtx.
  9679.         dir _ (m localPointToGlobal: dir) normalized.
  9680.         nextVtx _ B3DSimpleMeshVertex new.
  9681.         nextVtx position: dir x @ -1 @ dir z.
  9682.         nextVtx normal: 0@-1@0.
  9683.         nextVtx texCoord: (dir x @ dir z) * 0.5 + 0.5.
  9684.         midVtx _ nextVtx copy.
  9685.         midVtx position: 0@-1@0.
  9686.         midVtx texCoord:  0.5@0.5.
  9687.         face at: 2 put: nextVtx.
  9688.         face at: 3 put: midVtx.
  9689.         faceList nextPut: face.
  9690.         lastVtx _ nextVtx].
  9691.     ^faceList contents! !
  9692.  
  9693. !B3DIndexedMesh class methodsFor: 'vrml support' stamp: 'ar 9/16/1999 22:11'!
  9694. vrmlCreateBoxFaces
  9695.     | vtx face vtxSpec faceList |
  9696.     faceList _ WriteStream on: (Array new: 6).
  9697.     "front and back face"
  9698.     vtxSpec _ #(    ((-1 -1) (0 1))    (( 1 -1) (1 1))        (( 1  1) (1 0))    ((-1  1) (0 0))).
  9699.     "front"
  9700.     face _ B3DSimpleMeshFace new: 4.
  9701.     vtxSpec doWithIndex:[:spec :idx|
  9702.         vtx _ B3DSimpleMeshVertex new.
  9703.         vtx position: spec first first @ spec first second @ -1.
  9704.         vtx normal: 0@0@-1.
  9705.         vtx texCoord: spec second first @ spec second second.
  9706.         face at: idx put: vtx.
  9707.     ].
  9708.     faceList nextPut: face.
  9709.     "back"
  9710.     face _ B3DSimpleMeshFace new: 4.
  9711.     vtxSpec doWithIndex:[:spec :idx|
  9712.         vtx _ B3DSimpleMeshVertex new.
  9713.         vtx position: spec first first @ spec first second @ 1.
  9714.         vtx normal: 0@0@1.
  9715.         vtx texCoord: 1 - spec second first @ spec second second.
  9716.         face at: idx put: vtx.
  9717.     ].
  9718.     faceList nextPut: face.
  9719.     "top"
  9720.     face _ B3DSimpleMeshFace new: 4.
  9721.     vtxSpec doWithIndex:[:spec :idx|
  9722.         vtx _ B3DSimpleMeshVertex new.
  9723.         vtx position: spec first first @ 1 @ spec first second.
  9724.         vtx normal: 1@0@0.
  9725.         vtx texCoord: spec second first @ spec second second.
  9726.         face at: idx put: vtx.
  9727.     ].
  9728.     faceList nextPut: face.
  9729.     "bottom"
  9730.     face _ B3DSimpleMeshFace new: 4.
  9731.     vtxSpec doWithIndex:[:spec :idx|
  9732.         vtx _ B3DSimpleMeshVertex new.
  9733.         vtx position: spec first first @ -1 @ spec first second.
  9734.         vtx normal: -1@0@0.
  9735.         vtx texCoord: spec second first @ (1 - spec second second).
  9736.         face at: idx put: vtx.
  9737.     ].
  9738.     faceList nextPut: face.
  9739.     vtxSpec _ #(    ((-1 -1) (0 1))    ((-1  1) (1 1))        (( 1  1) (1 0))    (( 1 -1) (0 0))).
  9740.     "right"
  9741.     face _ B3DSimpleMeshFace new: 4.
  9742.     vtxSpec doWithIndex:[:spec :idx|
  9743.         vtx _ B3DSimpleMeshVertex new.
  9744.         vtx position: 1 @ spec first first @ spec first second.
  9745.         vtx normal: 1@0@0.
  9746.         vtx texCoord: spec second first @ spec second second.
  9747.         face at: idx put: vtx.
  9748.     ].
  9749.     faceList nextPut: face.
  9750.     "left"
  9751.     face _ B3DSimpleMeshFace new: 4.
  9752.     vtxSpec doWithIndex:[:spec :idx|
  9753.         vtx _ B3DSimpleMeshVertex new.
  9754.         vtx position: -1 @ spec first first @ spec first second.
  9755.         vtx normal: -1@0@0.
  9756.         vtx texCoord: 1 - spec second first @ spec second second.
  9757.         face at: idx put: vtx.
  9758.     ].
  9759.     faceList nextPut: face.
  9760.     ^faceList contents! !
  9761.  
  9762. !B3DIndexedMesh class methodsFor: 'vrml support' stamp: 'ar 9/16/1999 22:16'!
  9763. vrmlCreateCone: doSide bottom: doBottom
  9764.     | faces |
  9765.     faces _ #().
  9766.     doSide ifTrue:[faces _ faces, self vrmlCreateConeFaces].
  9767.     doBottom ifTrue:[faces _ faces, self vrmlCreateBottomFaces].
  9768.     ^(B3DSimpleMesh withAll: faces) asIndexedMesh! !
  9769.  
  9770. !B3DIndexedMesh class methodsFor: 'vrml support' stamp: 'ar 9/16/1999 22:07'!
  9771. vrmlCreateConeFaces
  9772.     | face steps dir m lastVtx nextVtx topVtx faceList |
  9773.     steps _ self vrmlSteps.
  9774.     faceList _ WriteStream on: (Array new: steps).
  9775.     dir _ 0@0@1.
  9776.     m _ (B3DRotation angle: (360.0 / steps) axis: (0@-1@0)) asMatrix4x4.
  9777.     lastVtx _ B3DSimpleMeshVertex new.
  9778.     lastVtx position: 0@-1@1.
  9779.     lastVtx normal: dir.
  9780.     lastVtx texCoord: 0@1.
  9781.     1 to: steps do:[:i|
  9782.         face _ B3DSimpleMeshFace new: 3.
  9783.         face at: 1 put: lastVtx.
  9784.         dir _ (m localPointToGlobal: dir) normalized.
  9785.         nextVtx _ B3DSimpleMeshVertex new.
  9786.         nextVtx position: dir x @ -1 @ dir z.
  9787.         nextVtx normal: dir.
  9788.         nextVtx texCoord: (i / steps asFloat) @ 1.
  9789.         topVtx _ nextVtx copy.
  9790.         topVtx position: 0@1@0.
  9791.         topVtx texCoord:  lastVtx texCoord x @ 0.
  9792.         face at: 2 put: nextVtx.
  9793.         face at: 3 put: topVtx.
  9794.         faceList nextPut: face.
  9795.         lastVtx _ nextVtx].
  9796.     ^faceList contents! !
  9797.  
  9798. !B3DIndexedMesh class methodsFor: 'vrml support' stamp: 'ar 9/16/1999 22:05'!
  9799. vrmlCreateCylinder: doSide bottom: doBottom top: doTop
  9800.     | faces |
  9801.     faces _ #().
  9802.     doSide ifTrue:[faces _ faces, self vrmlCreateCylinderFaces].
  9803.     doBottom ifTrue:[faces _ faces, self vrmlCreateBottomFaces].
  9804.     doTop ifTrue:[faces _ faces, self vrmlCreateTopFaces].
  9805.     ^(B3DSimpleMesh withAll: faces) asIndexedMesh! !
  9806.  
  9807. !B3DIndexedMesh class methodsFor: 'vrml support' stamp: 'ar 9/16/1999 22:07'!
  9808. vrmlCreateCylinderFaces
  9809.     | face steps dir m lastVtx nextVtx topVtx lastTopVtx faceList |
  9810.     steps _ self vrmlSteps.
  9811.     faceList _ WriteStream on: (Array new: steps).
  9812.     dir _ 0@0@1.
  9813.     m _ (B3DRotation angle: (360.0 / steps) axis: (0@-1@0)) asMatrix4x4.
  9814.     lastVtx _ B3DSimpleMeshVertex new.
  9815.     lastVtx position: 0@-1@1.
  9816.     lastVtx normal: dir.
  9817.     lastVtx texCoord: 0@1.
  9818.     lastTopVtx _ lastVtx copy.
  9819.     lastTopVtx position: 0@1@1.
  9820.     lastTopVtx texCoord: 0@0.
  9821.     1 to: steps do:[:i|
  9822.         face _ B3DSimpleMeshFace new: 4.
  9823.         face at: 1 put: lastVtx.
  9824.         face at: 4 put: lastTopVtx.
  9825.         dir _ (m localPointToGlobal: dir) normalized.
  9826.         nextVtx _ B3DSimpleMeshVertex new.
  9827.         nextVtx position: dir x @ -1 @ dir z.
  9828.         nextVtx normal: dir.
  9829.         nextVtx texCoord: (i / steps asFloat) @ 1.
  9830.         topVtx _ nextVtx copy.
  9831.         topVtx position: dir x @ 1 @  dir z.
  9832.         topVtx texCoord:  (i / steps asFloat) @ 0.
  9833.         face at: 2 put: nextVtx.
  9834.         face at: 3 put: topVtx.
  9835.         faceList nextPut: face.
  9836.         lastVtx _ nextVtx.
  9837.         lastTopVtx _ topVtx].
  9838.     ^faceList contents
  9839. ! !
  9840.  
  9841. !B3DIndexedMesh class methodsFor: 'vrml support' stamp: 'ar 9/16/1999 22:58'!
  9842. vrmlCreateSphereFaces
  9843.     "B3DIndexedMesh vrmlCreateSphereFaces"
  9844.     | faceList vtx steps m1 m2 baseDir vtxList vertices dir lastVtx nextVtx face |
  9845.     steps _ self vrmlSteps.
  9846.     faceList _ WriteStream on: (Array new: steps * steps).
  9847.     "<--- vertex construction --->"
  9848.     m1 _ (B3DRotation angle: 360.0 / steps axis: 0@-1@0) asMatrix4x4.
  9849.     m2 _ (B3DRotation angle: 180.0 / steps axis: 1@0@0) asMatrix4x4.
  9850.     baseDir _ 0@1@0.
  9851.     vtxList _ Array new: steps + 1.
  9852.     0 to: steps do:[:i|
  9853.         i = steps ifTrue:[baseDir _ 0@-1@0]. "Make closed for sure"
  9854.         vertices _ Array new: steps + 1.
  9855.         vtxList at: i+1 put: vertices.
  9856.         dir _ baseDir.
  9857.         0 to: steps do:[:j|
  9858.             j = steps ifTrue:[dir _ baseDir]. "Make closed for sure"
  9859.             vtx _ B3DSimpleMeshVertex new.
  9860.             vtx position: dir; normal: dir.
  9861.             vtx texCoord: (j / steps asFloat) @ (i / steps asFloat).
  9862.             vertices at: j+1 put: vtx.
  9863.             dir _ (m1 localPointToGlobal: dir) normalized.
  9864.         ].
  9865.         baseDir _ (m2 localPointToGlobal: baseDir) normalized.
  9866.     ].
  9867.     "<--- face construction --->"
  9868.     "Construct first round separately as triangles"
  9869.     lastVtx _ vtxList at: 1.
  9870.     nextVtx _ vtxList at: 2.
  9871.     1 to: steps do:[:i|
  9872.         face _ B3DSimpleMeshFace new: 3.
  9873.         face at: 1 put: (lastVtx at: i).
  9874.         face at: 2 put: (nextVtx at: i+1).
  9875.         face at: 3 put: (nextVtx at: i).
  9876.         faceList nextPut: face].
  9877.     "Construct the next rounds as quads"
  9878.     2 to: steps-1 do:[:i|
  9879.         lastVtx _ vtxList at: i.
  9880.         nextVtx _ vtxList at: i+1.
  9881.         1 to: steps do:[:j|
  9882.             face _ B3DSimpleMeshFace new: 4.
  9883.             face at: 1 put: (lastVtx at: j).
  9884.             face at: 2 put: (lastVtx at: j+1).
  9885.             face at: 3 put: (nextVtx at: j+1).
  9886.             face at: 4 put: (nextVtx at: j).
  9887.             faceList nextPut: face]].
  9888.     "Construct the last round separately as triangles"
  9889.     lastVtx _ vtxList at: steps.
  9890.     nextVtx _ vtxList at: steps+1.
  9891.     1 to: steps do:[:i|
  9892.         face _ B3DSimpleMeshFace new: 3.
  9893.         face at: 1 put: (lastVtx at: i).
  9894.         face at: 2 put: (lastVtx at: i+1).
  9895.         face at: 3 put: (nextVtx at: i).
  9896.         faceList nextPut: face].
  9897.     ^faceList contents! !
  9898.  
  9899. !B3DIndexedMesh class methodsFor: 'vrml support' stamp: 'ar 9/16/1999 22:08'!
  9900. vrmlCreateTopFaces
  9901.     | face steps dir m lastVtx nextVtx faceList midVtx |
  9902.     steps _ self vrmlSteps.
  9903.     faceList _ WriteStream on: (Array new: steps).
  9904.     dir _ 0@0@1.
  9905.     m _ (B3DRotation angle: (360.0 / steps) axis: (0@-1@0)) asMatrix4x4.
  9906.     lastVtx _ B3DSimpleMeshVertex new.
  9907.     lastVtx position: 0@1@1.
  9908.     lastVtx normal: 0@1@0.
  9909.     lastVtx texCoord: 0.5@0.
  9910.     1 to: steps do:[:i|
  9911.         face _ B3DSimpleMeshFace new: 3.
  9912.         face at: 1 put: lastVtx.
  9913.         dir _ (m localPointToGlobal: dir) normalized.
  9914.         nextVtx _ B3DSimpleMeshVertex new.
  9915.         nextVtx position: dir x @ 1 @ dir z.
  9916.         nextVtx normal: 0@1@0.
  9917.         nextVtx texCoord: (dir x @ dir z) * (0.5 @ -0.5) + 0.5.
  9918.         midVtx _ nextVtx copy.
  9919.         midVtx position: 0@1@0.
  9920.         midVtx texCoord:  0.5@0.5.
  9921.         face at: 2 put: nextVtx.
  9922.         face at: 3 put: midVtx.
  9923.         faceList nextPut: face.
  9924.         lastVtx _ nextVtx].
  9925.     ^faceList contents! !
  9926.  
  9927. !B3DIndexedMesh class methodsFor: 'vrml support' stamp: 'ar 9/16/1999 22:15'!
  9928. vrmlSteps
  9929.     "Return the number of steps for rotational objects"
  9930.     ^16! !
  9931.  
  9932. !B3DIndexedQuad methodsFor: 'initialize' stamp: 'ar 2/7/1999 20:00'!
  9933. with: i1 with: i2 with: i3 with: i4
  9934.     self at: 1 put: i1.
  9935.     self at: 2 put: i2.
  9936.     self at: 3 put: i3.
  9937.     self at: 4 put: i4.! !
  9938.  
  9939. !B3DIndexedQuad methodsFor: 'accessing' stamp: 'ar 2/8/1999 16:39'!
  9940. flags
  9941.     ^0! !
  9942.  
  9943. !B3DIndexedQuad methodsFor: 'private' stamp: 'ar 2/7/1999 20:02'!
  9944. replaceFrom: start to: stop with: replacement startingAt: repStart 
  9945.     "Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
  9946.     <primitive: 105>
  9947.     ^self primitiveFailed! !
  9948.  
  9949. !B3DIndexedQuad methodsFor: 'printing' stamp: 'ar 2/8/1999 16:39'!
  9950. printOn: aStream
  9951.     aStream nextPutAll:'IQuad(';
  9952.         print: (self at: 1);
  9953.         nextPutAll:', ';
  9954.         print: (self at: 2);
  9955.         nextPutAll:', ';
  9956.         print: (self at: 3);
  9957.         nextPutAll:', ';
  9958.         print: (self at: 4);
  9959.         nextPutAll:', ';
  9960.         print: (self flags);
  9961.         nextPutAll:')'.! !
  9962.  
  9963. !B3DIndexedQuad class methodsFor: 'instance creation' stamp: 'ar 2/7/1999 19:59'!
  9964. new
  9965.     ^self new: 4! !
  9966.  
  9967. !B3DIndexedQuad class methodsFor: 'instance creation' stamp: 'ar 2/7/1999 20:03'!
  9968. numElements
  9969.     ^4! !
  9970.  
  9971. !B3DIndexedQuad class methodsFor: 'instance creation' stamp: 'ar 2/7/1999 19:59'!
  9972. with: i1 with: i2 with: i3 with: i4
  9973.     ^self new with: i1 with: i2 with: i3 with: i4! !
  9974.  
  9975. !B3DIndexedQuadArray class methodsFor: 'accessing' stamp: 'ar 2/7/1999 19:58'!
  9976. contentsClass
  9977.     ^B3DIndexedQuad! !
  9978.  
  9979. !B3DIndexedQuadMesh methodsFor: 'displaying' stamp: 'ar 11/7/1999 18:35'!
  9980. renderOn: aRenderer
  9981.     ^aRenderer
  9982.         drawIndexedQuads: faces
  9983.             vertices: vertices
  9984.             normals: vtxNormals
  9985.             colors: vtxColors
  9986.             texCoords: vtxTexCoords.! !
  9987.  
  9988. !B3DIndexedQuadMesh methodsFor: 'private' stamp: 'ar 9/10/1999 15:05'!
  9989. plainTextureRect
  9990.     "Create a new plain rectangle w/ texture coords"
  9991.  
  9992.     vertices _ B3DVector3Array new: 4.
  9993.     vertices at: 1 put: (-1@-1@0).
  9994.     vertices at: 2 put: (1@-1@0).
  9995.     vertices at: 3 put: (1@1@0).
  9996.     vertices at: 4 put: (-1@1@0).
  9997.  
  9998.     vtxTexCoords _ B3DTexture2Array new: 4.
  9999.     vtxTexCoords at: 1 put: (0@1).
  10000.     vtxTexCoords at: 2 put: (1@1).
  10001.     vtxTexCoords at: 3 put: (1@0).
  10002.     vtxTexCoords at: 4 put: (0@0).
  10003.  
  10004.     faces _ B3DIndexedQuadArray new: 1.
  10005.     faces at: 1 put: (B3DIndexedQuad with: 1 with: 2 with: 3 with: 4).! !
  10006.  
  10007. !B3DIndexedQuadMesh methodsFor: 'private' stamp: 'ar 2/8/1999 02:15'!
  10008. sampleRect: n
  10009.     "B3DIndexedQuadMesh new sampleRect"
  10010.     | vtx face |
  10011.     vtx _ WriteStream on: (B3DVector3Array new).
  10012.     n negated to: n do:[:x|
  10013.         n negated to: n do:[:y|
  10014.             vtx nextPut: (B3DVector3 x: x y: y z: 0) /= n asFloat.
  10015.         ].
  10016.     ].
  10017.     vertices _ vtx contents.
  10018.     vtxNormals _ B3DVector3Array new: (2*n+1) squared.
  10019.     1 to: vtxNormals size do:[:i| vtxNormals at: i put: (0@0@-1)].
  10020.     faces _ B3DIndexedQuadArray new: (2*n) squared.
  10021.     0 to: 2*n-1 do:[:i|
  10022.         1 to: 2*n do:[:j|
  10023.             face _ B3DIndexedQuad 
  10024.                         with: (i*(2*n+1)+j)
  10025.                         with: (i*(2*n+1)+j+1)
  10026.                         with: (i+1*(2*n+1)+j+1)
  10027.                         with: (i+1*(2*n+1)+j).
  10028.             faces at: i*2*n+j put: face.
  10029.         ]].! !
  10030.  
  10031. !B3DIndexedTriangle methodsFor: 'initialize' stamp: 'ar 2/16/1999 19:09'!
  10032. with: index1 with: index2 with: index3
  10033.     self p1Index: index1.
  10034.     self p2Index: index2.
  10035.     self p3Index: index3.! !
  10036.  
  10037. !B3DIndexedTriangle methodsFor: 'accessing' stamp: 'ar 2/8/1999 05:15'!
  10038. flags
  10039.     ^0 "May be used later"! !
  10040.  
  10041. !B3DIndexedTriangle methodsFor: 'accessing' stamp: 'ar 2/8/1999 05:16'!
  10042. flags: aNumber
  10043.     ^self "Maybe used later"! !
  10044.  
  10045. !B3DIndexedTriangle methodsFor: 'accessing' stamp: 'ar 2/5/1999 22:54'!
  10046. p1Index
  10047.     ^self at: 1! !
  10048.  
  10049. !B3DIndexedTriangle methodsFor: 'accessing' stamp: 'ar 2/5/1999 22:55'!
  10050. p1Index: aNumber
  10051.     self at: 1 put: aNumber! !
  10052.  
  10053. !B3DIndexedTriangle methodsFor: 'accessing' stamp: 'ar 2/5/1999 22:55'!
  10054. p2Index
  10055.     ^self at: 2! !
  10056.  
  10057. !B3DIndexedTriangle methodsFor: 'accessing' stamp: 'ar 2/5/1999 22:55'!
  10058. p2Index: aNumber
  10059.     self at: 2 put: aNumber! !
  10060.  
  10061. !B3DIndexedTriangle methodsFor: 'accessing' stamp: 'ar 2/5/1999 22:55'!
  10062. p3Index
  10063.     ^self at: 3! !
  10064.  
  10065. !B3DIndexedTriangle methodsFor: 'accessing' stamp: 'ar 2/5/1999 22:55'!
  10066. p3Index: aNumber
  10067.     self at: 3 put: aNumber! !
  10068.  
  10069. !B3DIndexedTriangle methodsFor: 'testing' stamp: 'ar 2/8/1999 06:15'!
  10070. includesIndex: idx
  10071.     ^(self at: 1) = idx or:[(self at: 2) = idx or:[(self at: 3) = idx]]! !
  10072.  
  10073. !B3DIndexedTriangle methodsFor: 'private' stamp: 'ar 2/5/1999 23:19'!
  10074. replaceFrom: start to: stop with: replacement startingAt: repStart 
  10075.     "Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
  10076.     <primitive: 105>
  10077.     ^self primitiveFailed! !
  10078.  
  10079. !B3DIndexedTriangle methodsFor: 'printing' stamp: 'ar 2/8/1999 05:14'!
  10080. printOn: aStream
  10081.     aStream nextPutAll:'IFace(';
  10082.         print: self p1Index;
  10083.         nextPutAll:', ';
  10084.         print: self p2Index;
  10085.         nextPutAll:', ';
  10086.         print: self p3Index;
  10087.         nextPutAll:', ';
  10088.         print: self flags;
  10089.         nextPutAll:')'.! !
  10090.  
  10091. !B3DIndexedTriangle class methodsFor: 'instance creation' stamp: 'ar 2/8/1999 05:14'!
  10092. new
  10093.     ^self new: self numElements! !
  10094.  
  10095. !B3DIndexedTriangle class methodsFor: 'instance creation' stamp: 'ar 2/8/1999 05:15'!
  10096. numElements
  10097.     ^3! !
  10098.  
  10099. !B3DIndexedTriangle class methodsFor: 'instance creation' stamp: 'ar 2/16/1999 19:09'!
  10100. with: index1 with: index2 with: index3
  10101.     ^self new with: index1 with: index2 with: index3! !
  10102.  
  10103. !B3DIndexedTriangleArray class methodsFor: 'instance creation' stamp: 'ar 2/7/1999 20:56'!
  10104. contentsClass
  10105.     ^B3DIndexedTriangle! !
  10106.  
  10107. !B3DIndexedTriangleMesh methodsFor: 'displaying' stamp: 'ar 11/7/1999 18:35'!
  10108. renderOn: aRenderer
  10109.     self hasVertexColors ifTrue:[
  10110.         aRenderer trackAmbientColor: true.
  10111.         aRenderer trackDiffuseColor: true].
  10112.     ^aRenderer
  10113.         drawIndexedTriangles: faces
  10114.             vertices: vertices
  10115.             normals: vtxNormals
  10116.             colors: vtxColors
  10117.             texCoords: vtxTexCoords.! !
  10118.  
  10119. !B3DIndexedTriangleMesh methodsFor: 'private' stamp: 'ar 2/8/1999 02:15'!
  10120. sampleRect: n
  10121.     "B3DIndexedQuadMesh new sampleRect"
  10122.     | vtx face |
  10123.     vtx _ WriteStream on: (B3DVector3Array new).
  10124.     n negated to: n do:[:x|
  10125.         n negated to: n do:[:y|
  10126.             vtx nextPut: (B3DVector3 x: x y: y z: 0) /= n asFloat.
  10127.         ].
  10128.     ].
  10129.     vertices _ vtx contents.
  10130.     vtxNormals _ B3DVector3Array new: (2*n+1) squared.
  10131.     1 to: vtxNormals size do:[:i| vtxNormals at: i put: (0@0@-1)].
  10132.     faces _ B3DIndexedTriangleArray new: (2*n) squared.
  10133.     0 to: 2*n-1 do:[:i|
  10134.         1 to: 2*n do:[:j|
  10135.             face _ B3DIndexedTriangle 
  10136.                         with: (i*(2*n+1)+j)
  10137.                         with: (i*(2*n+1)+j+1)
  10138.                         with: (i+1*(2*n+1)+j+1)
  10139.                         "with: (i+1*(2*n+1)+j)".
  10140.             faces at: i*2*n+j put: face.
  10141.             "face _ B3DIndexedTriangle 
  10142.                         with: (i*(2*n+1)+j)
  10143.                         with: (i*(2*n+1)+j+1)
  10144.                         with: (i+1*(2*n+1)+j+1)
  10145.                         with: (i+1*(2*n+1)+j).
  10146.             "
  10147.         ]].! !
  10148.  
  10149. !B3DIndexedTriangleMesh methodsFor: 'fan creation' stamp: 'ar 2/8/1999 06:42'!
  10150. makeTriangleFans
  10151.     "Re-arrange the triangles so that they represent triangle fans."
  10152.     | vtxDict avgFacesPerVertex todo done maxShared maxSharedIndex newOrder sharedAssoc |
  10153.     "Compute the average size of faces per vertex (strange measure isn't it ;-)"
  10154.     avgFacesPerVertex _ faces size // vertices size + 3. "So we cover 99% of all cases"
  10155.     "vtxDict contains vertexIndex->(OrderedCollection of: IndexedFace)"
  10156.     vtxDict _ OrderedCollection new: vertices size.
  10157.     "Add all the vertex indexes. The set is larger than necessary to avoid collisions."
  10158.     1 to: vertices size do:[:i| vtxDict add: i -> (IdentitySet new: avgFacesPerVertex * 3)].
  10159.     "Go over all faces and add the face to all its vertices. Also store the faces in the toGo list."
  10160.     todo _ IdentitySet new: faces size * 3.
  10161.     done _ IdentitySet new: faces size * 3.
  10162.     faces do:[:iFace| 
  10163.         todo add: iFace.
  10164.         (vtxDict at: iFace p1Index) value add: iFace.
  10165.         (vtxDict at: iFace p2Index) value add: iFace.
  10166.         (vtxDict at: iFace p3Index) value add: iFace].
  10167.     "Now start creating the fans"
  10168.     [todo isEmpty] whileFalse:[
  10169.         "Let's assume that this method is not called in real-time 
  10170.         and spend some time to find the vertex with most shared faces"
  10171.         maxShared _ 0.
  10172.         maxSharedIndex _ nil.
  10173.         vtxDict doWithIndex:[:assoc :index| assoc value size > maxShared
  10174.             ifTrue:[maxShared _ assoc value size.
  10175.                     maxSharedIndex _ index]].
  10176.         maxSharedIndex = nil ifTrue:[^self error:'No shared vertices found'].
  10177.         "Now re-arrange the faces around the shared vertex"
  10178.         sharedAssoc _ vtxDict at: maxSharedIndex.
  10179.         newOrder _ self reArrangeFanFaces: sharedAssoc value around: sharedAssoc key from: todo into: done.
  10180.         "Remove re-arranged faces"
  10181.         newOrder do:[:iFace|
  10182.             (done includes: iFace) ifTrue:[self halt].
  10183.             todo remove: iFace.
  10184.             done add: iFace.
  10185.             (vtxDict at: iFace p1Index) value remove: iFace ifAbsent:[].
  10186.             (vtxDict at: iFace p2Index) value remove: iFace ifAbsent:[].
  10187.             (vtxDict at: iFace p3Index) value remove: iFace ifAbsent:[]].
  10188.         false ifTrue:[
  10189.         "Remove the shared index if no more faces left."
  10190.         sharedAssoc value isEmpty ifTrue:[
  10191.             vtxDict swap: maxSharedIndex with: vtxDict size.    "Optimized removal ;-)"
  10192.             vtxDict removeLast].
  10193.         ].
  10194.     ].! !
  10195.  
  10196. !B3DIndexedTriangleMesh methodsFor: 'fan creation' stamp: 'ar 2/8/1999 06:38'!
  10197. reArrangeFanFaces: sharedFaces around: maxSharedIndex from: todo into: done
  10198.     "Re-arrange the faces in sharedFaces to form a triangle fan.
  10199.     Avoid inplace-reversal of the triangles in doneList -- they have been arranged already"
  10200.     | out next nextIndex prevIndex index |
  10201.     out _ OrderedCollection new: sharedFaces size * 2.
  10202.     next _ sharedFaces detect:[:any| true].
  10203.     sharedFaces remove: next.
  10204.     out addLast: next.
  10205.     nextIndex _ next p1Index.
  10206.     nextIndex = maxSharedIndex ifTrue:[nextIndex _ next p2Index].
  10207.     prevIndex _ next p3Index.
  10208.     (prevIndex = maxSharedIndex) ifTrue:[prevIndex _ next p2Index].
  10209.     "Search forward"
  10210.     [next _ sharedFaces detect:[:iFace| iFace includesIndex: nextIndex] ifNone:[nil].
  10211.     next notNil] whileTrue:[
  10212.         sharedFaces remove: next.
  10213.         out addLast: next.
  10214.         index _ next p1Index.
  10215.         (index = maxSharedIndex or:[index = nextIndex]) ifTrue:[
  10216.             index _ next p2Index.
  10217.             (index = maxSharedIndex or:[index = nextIndex]) 
  10218.                 ifTrue:[index _ next p3Index]].
  10219.         nextIndex _ index].
  10220.     "Search backwards"
  10221.     nextIndex _ prevIndex.
  10222.     [next _ sharedFaces detect:[:iFace| iFace includesIndex: nextIndex] ifNone:[nil].
  10223.     next notNil] whileTrue:[
  10224.         sharedFaces remove: next.
  10225.         out addFirst: next.
  10226.         index _ next p1Index.
  10227.         (index = maxSharedIndex or:[index = nextIndex]) ifTrue:[
  10228.             index _ next p2Index.
  10229.             (index = maxSharedIndex or:[index = nextIndex]) 
  10230.                 ifTrue:[index _ next p3Index]].
  10231.         nextIndex _ index].
  10232.     ^out! !
  10233.  
  10234. !B3DInplaceArray methodsFor: 'accessing' stamp: 'ar 2/5/1999 22:49'!
  10235. at: index
  10236.     "Return the primitive vertex at the given index"
  10237.     | vtx |
  10238.     (index < 1 or:[index > self size]) ifTrue:[^self errorSubscriptBounds: index].
  10239.     vtx _ self contentsClass new.
  10240.     vtx replaceFrom: 1 to: vtx size with: self startingAt: index - 1 * self contentsSize + 1.
  10241.     ^vtx! !
  10242.  
  10243. !B3DInplaceArray methodsFor: 'accessing' stamp: 'ar 2/6/1999 00:12'!
  10244. at: index put: anObject
  10245.     "Store the object at the given index in the receiver"
  10246.     | idx |
  10247.     (index < 1 or:[index > self size]) ifTrue:[^self errorSubscriptBounds: index].
  10248.     idx _ index - 1 * self contentsSize.
  10249.     self privateReplaceFrom: idx+1 to: idx + self contentsSize with: anObject startingAt: 1.
  10250.     ^anObject! !
  10251.  
  10252. !B3DInplaceArray methodsFor: 'accessing' stamp: 'ar 2/5/1999 22:48'!
  10253. contentsClass
  10254.     ^self class contentsClass! !
  10255.  
  10256. !B3DInplaceArray methodsFor: 'accessing' stamp: 'ar 2/5/1999 22:48'!
  10257. contentsSize
  10258.     ^self contentsClass numElements! !
  10259.  
  10260. !B3DInplaceArray methodsFor: 'accessing' stamp: 'ar 2/5/1999 22:49'!
  10261. size
  10262.     "Return the number of primitive vertices that can be stored in the receiver"
  10263.     ^self basicSize // self contentsSize! !
  10264.  
  10265. !B3DInplaceArray methodsFor: 'copying' stamp: 'ar 2/7/1999 19:48'!
  10266. copyFrom: start to: stop 
  10267.     "Answer a copy of a subset of the receiver, starting from element at 
  10268.     index start until element at index stop."
  10269.  
  10270.     | newSize |
  10271.     newSize _ stop - start + 1.
  10272.     ^(self species new: newSize)
  10273.         replaceFrom: 1
  10274.         to: newSize
  10275.         with: self
  10276.         startingAt: start! !
  10277.  
  10278. !B3DInplaceArray methodsFor: 'private' stamp: 'ar 2/6/1999 00:39'!
  10279. privateReplaceFrom: start to: stop with: replacement startingAt: repStart 
  10280.     <primitive: 105>
  10281.     start to: stop do:[:i|
  10282.         self basicAt: i put: (replacement at: i - start + repStart).
  10283.     ].! !
  10284.  
  10285. !B3DInplaceArray methodsFor: 'private' stamp: 'ar 2/7/1999 19:46'!
  10286. replaceFrom: start to: stop with: replacement startingAt: repStart
  10287.     | max |
  10288.     max _ (replacement size - repStart) min: stop-start.
  10289.     start to: start+max do:[:i|
  10290.         self at: i put: (replacement at: i - start + repStart).
  10291.     ].! !
  10292.  
  10293. !B3DInplaceArray methodsFor: 'enumerating' stamp: 'ar 2/6/1999 00:37'!
  10294. do: aBlock
  10295.     "Overridden to store the (possibly) modified argument back"
  10296.     | obj |
  10297.     1 to: self size do:[:index|
  10298.         obj _ self at: index.
  10299.         aBlock value: obj.
  10300.         self at: index put: obj].! !
  10301.  
  10302. !B3DInplaceArray methodsFor: 'enumerating' stamp: 'ar 2/6/1999 00:37'!
  10303. readOnlyDo: aBlock
  10304.     ^super do: aBlock! !
  10305.  
  10306. !B3DInplaceArray class methodsFor: 'instance creation' stamp: 'ar 2/5/1999 22:48'!
  10307. contentsClass
  10308.     ^self subclassResponsibility! !
  10309.  
  10310. !B3DInplaceArray class methodsFor: 'instance creation' stamp: 'ar 2/5/1999 22:49'!
  10311. contentsSize
  10312.     ^self contentsClass numElements! !
  10313.  
  10314. !B3DInplaceArray class methodsFor: 'instance creation' stamp: 'ar 2/5/1999 22:49'!
  10315. new: n
  10316.     ^super new: self contentsSize*n! !
  10317.  
  10318. I represent the attenuation for any given light source, e.g., how the intensity of the light is reduced with increasing distance from the object. I consist of three parts, a constant part, a linear part and a squared part. The resulting intensity for any given distance d is computed by:
  10319.  
  10320.     intensity _ 1.0 / (constantPart + (distance * linearPart) + (distance^2 * squaredPart)).
  10321. !
  10322. !B3DLightAttenuation methodsFor: 'initialize' stamp: 'ar 2/7/1999 19:02'!
  10323. constant: constantFactor linear: linearFactor squared: squaredFactor
  10324.     self constantPart: constantFactor.
  10325.     self linearPart: linearFactor.
  10326.     self squaredPart: squaredFactor.! !
  10327.  
  10328. !B3DLightAttenuation methodsFor: 'accessing' stamp: 'ar 2/6/1999 18:44'!
  10329. constantPart
  10330.     ^self floatAt: 1! !
  10331.  
  10332. !B3DLightAttenuation methodsFor: 'accessing' stamp: 'ar 2/6/1999 18:45'!
  10333. constantPart: aNumber
  10334.     self floatAt: 1 put: aNumber! !
  10335.  
  10336. !B3DLightAttenuation methodsFor: 'accessing' stamp: 'ar 2/6/1999 18:45'!
  10337. linearPart
  10338.     ^self floatAt: 2! !
  10339.  
  10340. !B3DLightAttenuation methodsFor: 'accessing' stamp: 'ar 2/6/1999 18:45'!
  10341. linearPart: aNumber
  10342.     self floatAt: 2 put: aNumber! !
  10343.  
  10344. !B3DLightAttenuation methodsFor: 'accessing' stamp: 'ar 2/6/1999 18:45'!
  10345. squaredPart
  10346.     ^self floatAt: 3! !
  10347.  
  10348. !B3DLightAttenuation methodsFor: 'accessing' stamp: 'ar 2/6/1999 18:45'!
  10349. squaredPart: aNumber
  10350.     self floatAt: 3 put: aNumber! !
  10351.  
  10352. !B3DLightAttenuation methodsFor: 'lighting' stamp: 'ar 2/6/1999 18:44'!
  10353. computeAttenuationFor: distance
  10354.     "Compute the light attenuation for the given distance"
  10355.     ^1.0 / (self constantPart + 
  10356.             (distance * (self linearPart + 
  10357.                 (distance * self squaredPart))))! !
  10358.  
  10359. !B3DLightAttenuation methodsFor: 'testing' stamp: 'ar 2/15/1999 21:58'!
  10360. isIdentity
  10361.     "Return true if the attenuation results in a constant lighting"
  10362.     ^self constantPart = 1.0
  10363.         and:[self linearPart = 0.0
  10364.             and:[self squaredPart = 0.0]]! !
  10365.  
  10366. !B3DLightAttenuation class methodsFor: 'instance creation' stamp: 'ar 2/7/1999 19:01'!
  10367. constant: constantFactor linear: linearFactor squared: squaredFactor
  10368.     ^self new constant: constantFactor linear: linearFactor squared: squaredFactor! !
  10369.  
  10370. !B3DLightAttenuation class methodsFor: 'instance creation' stamp: 'ar 2/6/1999 18:46'!
  10371. numElements
  10372.     ^3! !
  10373.  
  10374. !B3DLightSource methodsFor: 'shading' stamp: 'ar 2/7/1999 16:51'!
  10375. computeAttenuationFor: distance
  10376.     ^self subclassResponsibility! !
  10377.  
  10378. !B3DLightSource methodsFor: 'shading' stamp: 'ar 2/7/1999 16:51'!
  10379. computeDirectionTo: aB3DPrimitiveVertex
  10380.     ^self subclassResponsibility! !
  10381.  
  10382. !B3DLightSource methodsFor: 'shading' stamp: 'ar 2/15/1999 02:26'!
  10383. computeSpotFactor: light2Vertex
  10384.     "Compute the spot factor for a spot light"
  10385.     | lightDirection cosAngle minCos deltaCos maxCos |
  10386.     lightDirection _ self direction.
  10387.     cosAngle _ (lightDirection dot: light2Vertex) negated.
  10388.     (cosAngle < (minCos _ self hotSpotMinCosine)) ifTrue:[^0.0].
  10389.     maxCos _ self hotSpotMaxCosine.
  10390. "    maxCos = 1.0 ifFalse:["
  10391.         deltaCos _ self hotSpotDeltaCosine.
  10392.         deltaCos <= 0.00001 ifTrue:[
  10393.             "No delta -- a sharp boundary between on and off.
  10394.             Since off has already been determined above, we are on"
  10395.             ^1.0].
  10396.         "Scale the angle to 0/1 range"
  10397.         cosAngle _ (cosAngle - minCos) / deltaCos.
  10398.         self flag: #TODO. "Don't scale by (maxCos - minCos)"
  10399. "    ]."
  10400.     self flag: #TODO. "Use table lookup for spot exponent"
  10401.     ^cosAngle raisedTo: self spotExponent! !
  10402.  
  10403. !B3DLightSource methodsFor: 'shading' stamp: 'ar 2/15/1999 03:55'!
  10404. shadeVertexBuffer: vb with: aMaterial into: colorArray
  10405.     "This is the generic shading function similar to the primitive.
  10406.     Subclasses may implement optimized versions but should evaluate
  10407.     exactly to the same value as in here if they are to be converted into
  10408.     B3DPrimitiveLights."
  10409.     | color vtxArray ambientColor vtx direction distance scale cosAngle diffusePart specularPart specDir specularFactor |
  10410.     self flag: #b3dPrimitive.
  10411.     vtxArray _ vb vertexArray.
  10412.     (self hasAmbientPart and:[vb trackAmbientColor not])
  10413.         ifTrue:[ambientColor _ aMaterial ambientPart * lightColor ambientPart].
  10414.     (self hasDiffusePart and:[vb trackDiffuseColor not])
  10415.         ifTrue:[diffusePart _ aMaterial diffusePart].
  10416.     (self hasSpecularPart and:[vb trackSpecularColor not])
  10417.         ifTrue:[specularPart _ aMaterial specularPart].
  10418.     1 to: vb vertexCount do:[:i|
  10419.         vtx _ vtxArray at: i.
  10420.         color _ colorArray at: i.
  10421.  
  10422.         "Compute the direction and distance of light source from vertex"
  10423.         direction _ self computeDirectionTo: vtx.
  10424.         distance _ direction length.
  10425.         (distance = 0.0 or:[distance = 1.0]) ifFalse:[direction /= distance negated].
  10426.  
  10427.         "Compute the attenuation for the given distance"
  10428.         self isAttenuated
  10429.             ifTrue:[scale _ self computeAttenuationFor: distance]
  10430.             ifFalse:[scale _ 1.0].
  10431.  
  10432.         "Compute spot light factor"
  10433.         self hasSpot
  10434.             ifTrue:[scale _ scale * (self computeSpotFactor: direction)].
  10435.  
  10436.         "Compute ambient part"
  10437.         self hasAmbientPart ifTrue:[
  10438.             vb trackAmbientColor 
  10439.                 ifTrue:[ambientColor _ vtx b3dColor * lightColor ambientPart].
  10440.             color += (ambientColor * scale).
  10441.         ].
  10442.  
  10443.         "Compute the diffuse part of the light"
  10444.         self hasDiffusePart ifTrue:[
  10445.             "Compute angle from light->vertex to vertex normal"
  10446.             cosAngle _ vtx normal dot: direction.
  10447.             "For one-sided lighting negate cosAngle if necessary"
  10448.             (vb twoSidedLighting not and:[cosAngle < 0.0]) 
  10449.                 ifTrue:[cosAngle _ 0.0 - cosAngle].
  10450.             "For two-sided lighting check if cosAngle > 0.0 meaning that it is a front face"
  10451.             cosAngle > 0.0 ifTrue:[
  10452.                 vb trackDiffuseColor ifTrue:[diffusePart _ vtx b3dColor].
  10453.                 color += (diffusePart * lightColor diffusePart * (cosAngle * scale)).
  10454.             ].
  10455.         ].
  10456.  
  10457.         "Compute specular part of the light"
  10458.         (self hasSpecularPart and:[aMaterial shininess > 0.0]) ifTrue:[
  10459.             vb useLocalViewer 
  10460.                 ifTrue:[specDir _ direction - vtx position safelyNormalized]
  10461.                 ifFalse:[specDir _ direction - (0@0@1.0)].
  10462.             cosAngle _ vtx normal dot: specDir.
  10463.             cosAngle > 0.0 ifTrue:[
  10464.                 "Normalize the angle"
  10465.                 cosAngle _ cosAngle / specDir length.
  10466.                 "cosAngle should be somewhere between 0 and 1.
  10467.                 If not, then the vertex normal was not normalized"
  10468.                 cosAngle > 1.0 ifTrue:[
  10469.                     specularFactor _ cosAngle raisedTo: aMaterial shininess.
  10470.                 ] ifFalse:[
  10471.                     self flag: #TODO. "Use table lookup later"
  10472.                     specularFactor _ cosAngle raisedTo: self shininess.
  10473.                 ].
  10474.                 color += (specularPart * lightColor specularPart * specularFactor).
  10475.             ].
  10476.         ].
  10477.         self flag: #TODO. "Check specular part"
  10478.         colorArray at: i put: color.
  10479.     ].! !
  10480.  
  10481. !B3DLightSource methodsFor: 'accessing' stamp: 'ar 2/7/1999 18:17'!
  10482. direction
  10483.     "If the light is directional, return the NORMALIZED direction of the light"
  10484.     ^B3DVector3 zero! !
  10485.  
  10486. !B3DLightSource methodsFor: 'accessing' stamp: 'ar 2/7/1999 18:28'!
  10487. hotSpotDeltaCosine
  10488.     "Return the cosine value of the delta radius of a spot light (the fall off region)"
  10489.     ^self hotSpotMaxCosine - self hotSpotMinCosine! !
  10490.  
  10491. !B3DLightSource methodsFor: 'accessing' stamp: 'ar 2/7/1999 18:27'!
  10492. hotSpotMaxCosine
  10493.     "Return the cosine value of the outer radius of a spot light (the unlit region)"
  10494.     ^0.0! !
  10495.  
  10496. !B3DLightSource methodsFor: 'accessing' stamp: 'ar 2/7/1999 18:26'!
  10497. hotSpotMinCosine
  10498.     "Return the cosine value of the inner radius of a spot light (the fully lit region)"
  10499.     ^0.0! !
  10500.  
  10501. !B3DLightSource methodsFor: 'accessing' stamp: 'ar 2/8/1999 16:53'!
  10502. lightColor
  10503.     ^lightColor! !
  10504.  
  10505. !B3DLightSource methodsFor: 'accessing' stamp: 'ar 2/8/1999 16:53'!
  10506. lightColor: aMaterialColor
  10507.     lightColor _ aMaterialColor! !
  10508.  
  10509. !B3DLightSource methodsFor: 'accessing' stamp: 'ti 3/27/2000 14:21'!
  10510. spotExponent
  10511.     "Return the exponent to be used for the spot fall off computation"
  10512.     ^1.0! !
  10513.  
  10514. !B3DLightSource methodsFor: 'testing' stamp: 'ar 2/7/1999 17:22'!
  10515. hasAmbientPart
  10516.     "Return true if the receiver contains an ambient part in its color"
  10517.     ^true! !
  10518.  
  10519. !B3DLightSource methodsFor: 'testing' stamp: 'ar 2/15/1999 23:07'!
  10520. hasDiffusePart
  10521.     "Return true if the receiver contains a diffuse part in its color"
  10522.     ^true! !
  10523.  
  10524. !B3DLightSource methodsFor: 'testing' stamp: 'ar 2/15/1999 23:07'!
  10525. hasSpecularPart
  10526.     "Return true if the receiver contains a specular part in its color"
  10527.     ^true! !
  10528.  
  10529. !B3DLightSource methodsFor: 'testing' stamp: 'ar 2/7/1999 18:52'!
  10530. hasSpot
  10531.     "Return true if the receiver has a hot spot."
  10532.     ^false! !
  10533.  
  10534. !B3DLightSource methodsFor: 'testing' stamp: 'ar 2/7/1999 17:27'!
  10535. isAttenuated
  10536.     "Return true if the receiver contains an attenuation.
  10537.     If so, #computeAttenuationFor: must return the attenuation for the given distance."
  10538.     ^true! !
  10539.  
  10540. !B3DLightSource methodsFor: 'converting' stamp: 'ar 2/7/1999 06:45'!
  10541. asPrimitiveLight
  10542.     "Convert the receiver into a B3DPrimitiveLight that can be handled by the shader primitive directly. Light sources that cannot be represented as primitive should return nil. This will result in the callback of #shadeVertexBuffer from the shader."
  10543.     ^nil! !
  10544.  
  10545. !B3DLightSource methodsFor: 'converting' stamp: 'ar 2/8/1999 01:29'!
  10546. transformedBy: aTransformer
  10547.     ^self clone! !
  10548.  
  10549. !B3DLightSource methodsFor: 'private' stamp: 'ar 2/7/1999 16:37'!
  10550. setColor: aColor
  10551.     lightColor _ B3DMaterialColor new.
  10552.     lightColor ambientPart: aColor.
  10553.     lightColor diffusePart: aColor.
  10554.     lightColor specularPart: aColor.! !
  10555.  
  10556. !B3DLightSource class methodsFor: 'instance creation' stamp: 'ar 2/7/1999 16:09'!
  10557. color: aColor
  10558.     ^self new setColor: aColor.! !
  10559.  
  10560. !B3DMaterial methodsFor: 'initialize' stamp: 'ar 2/16/1999 03:05'!
  10561. from3DS: aDictionary
  10562.     self ambientPart: (aDictionary at: #ambient ifAbsent:[B3DColor4 r: 0.0 g: 0.0 b: 0.0 a: 1.0]).
  10563.     self diffusePart: (aDictionary at: #diffuse ifAbsent:[B3DColor4 r: 0.0 g: 0.0 b: 0.0 a: 1.0]).
  10564.     self specularPart: (aDictionary at: #specular ifAbsent:[B3DColor4 r: 0.0 g: 0.0 b: 0.0 a: 1.0]).
  10565.     (aDictionary includesKey: #textureName) 
  10566.         ifTrue:[^(aDictionary at: #textureName) -> self].! !
  10567.  
  10568. !B3DMaterial methodsFor: 'accessing' stamp: 'ar 2/8/1999 00:54'!
  10569. emission
  10570.     ^B3DColor4
  10571.         r: self emissionRed
  10572.         g: self emissionGreen
  10573.         b: self emissionBlue
  10574.         a: self emissionAlpha! !
  10575.  
  10576. !B3DMaterial methodsFor: 'accessing' stamp: 'ar 2/8/1999 00:53'!
  10577. emission: aColor
  10578.     self emissionRed: aColor red.
  10579.     self emissionGreen: aColor green.
  10580.     self emissionBlue: aColor blue.
  10581.     self emissionAlpha: aColor alpha.! !
  10582.  
  10583. !B3DMaterial methodsFor: 'accessing' stamp: 'ar 2/8/1999 00:58'!
  10584. shininess
  10585.     ^self floatAt: 17! !
  10586.  
  10587. !B3DMaterial methodsFor: 'accessing' stamp: 'ar 2/8/1999 00:59'!
  10588. shininess: aFloat
  10589.     ^self floatAt: 17 put: (aFloat max: 0.0).! !
  10590.  
  10591. !B3DMaterial methodsFor: 'element access' stamp: 'ar 2/8/1999 00:58'!
  10592. emissionAlpha
  10593.     ^self floatAt: 16! !
  10594.  
  10595. !B3DMaterial methodsFor: 'element access' stamp: 'ar 2/8/1999 00:59'!
  10596. emissionAlpha: aFloat
  10597.     self floatAt: 16 put: aFloat! !
  10598.  
  10599. !B3DMaterial methodsFor: 'element access' stamp: 'ar 2/8/1999 00:58'!
  10600. emissionBlue
  10601.     ^self floatAt: 15! !
  10602.  
  10603. !B3DMaterial methodsFor: 'element access' stamp: 'ar 2/8/1999 00:59'!
  10604. emissionBlue: aFloat
  10605.     self floatAt: 15 put: aFloat! !
  10606.  
  10607. !B3DMaterial methodsFor: 'element access' stamp: 'ar 2/8/1999 00:58'!
  10608. emissionGreen
  10609.     ^self floatAt: 14! !
  10610.  
  10611. !B3DMaterial methodsFor: 'element access' stamp: 'ar 2/8/1999 00:59'!
  10612. emissionGreen: aFloat
  10613.     self floatAt: 14 put: aFloat! !
  10614.  
  10615. !B3DMaterial methodsFor: 'element access' stamp: 'ar 2/8/1999 00:58'!
  10616. emissionRed
  10617.     ^self floatAt: 13! !
  10618.  
  10619. !B3DMaterial methodsFor: 'element access' stamp: 'ar 2/8/1999 00:59'!
  10620. emissionRed: aFloat
  10621.     self floatAt: 13 put: aFloat! !
  10622.  
  10623. !B3DMaterial class methodsFor: 'instance creation' stamp: 'ar 2/8/1999 01:01'!
  10624. from3DS: aDictionary
  10625.     ^self new from3DS: aDictionary! !
  10626.  
  10627. !B3DMaterial class methodsFor: 'instance creation' stamp: 'ar 2/8/1999 01:00'!
  10628. numElements
  10629.     ^17! !
  10630.  
  10631. !B3DMaterialColor methodsFor: 'accessing' stamp: 'ar 2/6/1999 18:58'!
  10632. ambientPart
  10633.     ^B3DColor4
  10634.         r: self ambientRed
  10635.         g: self ambientGreen
  10636.         b: self ambientBlue
  10637.         a: self ambientAlpha! !
  10638.  
  10639. !B3DMaterialColor methodsFor: 'accessing' stamp: 'ar 2/6/1999 19:00'!
  10640. ambientPart: aColor
  10641.     self ambientRed: aColor red.
  10642.     self ambientGreen: aColor green.
  10643.     self ambientBlue: aColor blue.
  10644.     self ambientAlpha: aColor alpha.! !
  10645.  
  10646. !B3DMaterialColor methodsFor: 'accessing' stamp: 'ar 2/6/1999 18:58'!
  10647. diffusePart
  10648.     ^B3DColor4
  10649.         r: self diffuseRed
  10650.         g: self diffuseGreen
  10651.         b: self diffuseBlue
  10652.         a: self diffuseAlpha! !
  10653.  
  10654. !B3DMaterialColor methodsFor: 'accessing' stamp: 'ar 2/6/1999 19:00'!
  10655. diffusePart: aColor
  10656.     self diffuseRed: aColor red.
  10657.     self diffuseGreen: aColor green.
  10658.     self diffuseBlue: aColor blue.
  10659.     self diffuseAlpha: aColor alpha.! !
  10660.  
  10661. !B3DMaterialColor methodsFor: 'accessing' stamp: 'ar 2/6/1999 18:59'!
  10662. specularPart
  10663.     ^B3DColor4
  10664.         r: self specularRed
  10665.         g: self specularGreen
  10666.         b: self specularBlue
  10667.         a: self specularAlpha! !
  10668.  
  10669. !B3DMaterialColor methodsFor: 'accessing' stamp: 'ar 2/6/1999 19:01'!
  10670. specularPart: aColor
  10671.     self specularRed: aColor red.
  10672.     self specularGreen: aColor green.
  10673.     self specularBlue: aColor blue.
  10674.     self specularAlpha: aColor alpha.! !
  10675.  
  10676. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:01'!
  10677. ambientAlpha
  10678.     ^self floatAt: 4! !
  10679.  
  10680. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:02'!
  10681. ambientAlpha: aFloat
  10682.     ^self floatAt: 4 put: aFloat! !
  10683.  
  10684. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:01'!
  10685. ambientBlue
  10686.     ^self floatAt: 3! !
  10687.  
  10688. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:02'!
  10689. ambientBlue: aFloat
  10690.     ^self floatAt: 3 put: aFloat! !
  10691.  
  10692. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:01'!
  10693. ambientGreen
  10694.     ^self floatAt: 2! !
  10695.  
  10696. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:02'!
  10697. ambientGreen: aFloat
  10698.     ^self floatAt: 2 put: aFloat! !
  10699.  
  10700. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:01'!
  10701. ambientRed
  10702.     ^self floatAt: 1! !
  10703.  
  10704. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:03'!
  10705. ambientRed: aFloat
  10706.     ^self floatAt: 1 put: aFloat! !
  10707.  
  10708. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:02'!
  10709. diffuseAlpha
  10710.     ^self floatAt: 8! !
  10711.  
  10712. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:03'!
  10713. diffuseAlpha: aFloat
  10714.     ^self floatAt: 8 put: aFloat! !
  10715.  
  10716. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:02'!
  10717. diffuseBlue
  10718.     ^self floatAt: 7! !
  10719.  
  10720. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:03'!
  10721. diffuseBlue: aFloat
  10722.     ^self floatAt: 7 put: aFloat! !
  10723.  
  10724. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:01'!
  10725. diffuseGreen
  10726.     ^self floatAt: 6! !
  10727.  
  10728. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:03'!
  10729. diffuseGreen: aFloat
  10730.     ^self floatAt: 6 put: aFloat! !
  10731.  
  10732. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:01'!
  10733. diffuseRed
  10734.     ^self floatAt: 5! !
  10735.  
  10736. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:03'!
  10737. diffuseRed: aFloat
  10738.     ^self floatAt: 5 put: aFloat! !
  10739.  
  10740. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:02'!
  10741. specularAlpha
  10742.     ^self floatAt: 12! !
  10743.  
  10744. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:03'!
  10745. specularAlpha: aFloat
  10746.     ^self floatAt: 12 put: aFloat! !
  10747.  
  10748. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:02'!
  10749. specularBlue
  10750.     ^self floatAt: 11! !
  10751.  
  10752. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:03'!
  10753. specularBlue: aFloat
  10754.     ^self floatAt: 11 put: aFloat! !
  10755.  
  10756. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:02'!
  10757. specularGreen
  10758.     ^self floatAt: 10! !
  10759.  
  10760. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:04'!
  10761. specularGreen: aFloat
  10762.     ^self floatAt: 10 put: aFloat! !
  10763.  
  10764. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:02'!
  10765. specularRed
  10766.     ^self floatAt: 9! !
  10767.  
  10768. !B3DMaterialColor methodsFor: 'element access' stamp: 'ar 2/6/1999 19:04'!
  10769. specularRed: aFloat
  10770.     ^self floatAt: 9 put: aFloat! !
  10771.  
  10772. !B3DMaterialColor methodsFor: 'private' stamp: 'ar 2/7/1999 18:41'!
  10773. setColor: aColor
  10774.     self ambientPart: aColor.
  10775.     self diffusePart: aColor.
  10776.     self specularPart: aColor.! !
  10777.  
  10778. !B3DMaterialColor class methodsFor: 'instance creation' stamp: 'ar 2/7/1999 18:41'!
  10779. color: aColor
  10780.     ^self new setColor: aColor! !
  10781.  
  10782. !B3DMaterialColor class methodsFor: 'instance creation' stamp: 'ar 2/6/1999 19:04'!
  10783. numElements
  10784.     ^12! !
  10785.  
  10786. I represent a general 4x4 transformation matrix commonly used in computer graphics.!
  10787. !B3DMatrix4x4 methodsFor: 'initialize' stamp: 'ar 2/1/1999 21:26'!
  10788. setBSplineBase
  10789.     "Set the receiver to the BSpline base matrix"
  10790.     "for further information see:
  10791.         Foley, van Dam, Feiner, Hughes
  10792.         'Computer Graphics: Principles and Practice'
  10793.         Addison-Wesley Publishing Company
  10794.         Second Edition, pp. 505"
  10795.     self
  10796.         a11: -1.0 / 6.0;    a12: 3.0 / 6.0;    a13: -3.0 / 6.0;    a14: 1.0 / 6.0;
  10797.         a21: 3.0 / 6.0;    a22: -6.0 / 6.0;    a23: 3.0 / 6.0;    a24: 0.0 / 6.0;
  10798.         a31: -3.0 / 6.0;    a32: 0.0 / 6.0;    a33: 3.0 / 6.0;    a34: 0.0 / 6.0;
  10799.         a41: 1.0 / 6.0;    a42: 4.0 / 6.0;    a43: 1.0 / 6.0;    a44: 0.0 / 6.0
  10800. ! !
  10801.  
  10802. !B3DMatrix4x4 methodsFor: 'initialize' stamp: 'ar 2/1/1999 21:26'!
  10803. setBetaSplineBaseBias: beta1 tension: beta2
  10804.     "Set the receiver to the betaSpline base matrix 
  10805.     if beta1=1 and beta2=0 then the bSpline base matrix will be returned"
  10806.     "for further information see:
  10807.         Foley, van Dam, Feiner, Hughes
  10808.         'Computer Graphics: Principles and Practice'
  10809.         Addison-Wesley Publishing Company
  10810.         Second Edition, pp. 505"
  10811.     | b12 b13 delta |
  10812.     b12 := beta1 * beta1.
  10813.     b13 := beta1 * b12.
  10814.     delta := 1.0 / (beta2 + (2.0 * b13) + 4.0 * (b12 + beta1) +2.0).
  10815.     
  10816.     self
  10817.         a11: delta * -2.0 * b13;
  10818.         a12: delta * 2.0 * (beta2 + b13 + b12 + beta1);
  10819.         a13: delta * -2.0 * (beta2 + b12 + beta1 + 1.0);
  10820.         a14: delta * 2.0;
  10821.         a21: delta * 6.0 * b13;
  10822.         a22: delta * -3.0 * (beta2 + (2.0 * (b13 + b12)));
  10823.         a23: delta * 3.0 * (beta2 + (2.0 * b12));
  10824.         a24: 0.0;
  10825.         a31: delta * -6.0 * b13;
  10826.         a32: delta * 6.0 * (b13 - beta1);
  10827.         a33: delta * 6.0 * beta1;
  10828.         a34: 0.0;
  10829.         a41: delta * 2.0 * b13;
  10830.         a42: delta * (beta2 + 4.0 * (b12 + beta1));
  10831.         a43: delta * 2.0;
  10832.         a44: 0.0
  10833. ! !
  10834.  
  10835. !B3DMatrix4x4 methodsFor: 'initialize' stamp: 'ar 2/1/1999 21:27'!
  10836. setBezierBase
  10837.     "Set the receiver to the bezier base matrix"
  10838.     "for further information see:
  10839.         Foley, van Dam, Feiner, Hughes
  10840.         'Computer Graphics: Principles and Practice'
  10841.         Addison-Wesley Publishing Company
  10842.         Second Edition, pp. 505"
  10843.     self
  10844.         a11: -1.0;        a12: 3.0;        a13: -3.0;    a14: 1.0;
  10845.         a21: 3.0;        a22: -6.0;    a23: 3.0;    a24: 0.0;
  10846.         a31: -3.0;    a32: 3.0;    a33: 0.0;    a34: 0.0;
  10847.         a41: 1.0;        a42: 0.0;    a43: 0.0;    a44: 0.0! !
  10848.  
  10849. !B3DMatrix4x4 methodsFor: 'initialize' stamp: 'ar 2/1/1999 21:27'!
  10850. setCardinalBase
  10851.     "Set the receiver to the cardinal spline base matrix - just catmull * 2"
  10852.     "for further information see:
  10853.         Foley, van Dam, Feiner, Hughes
  10854.         'Computer Graphics: Principles and Practice'
  10855.         Addison-Wesley Publishing Company
  10856.         Second Edition, pp. 505"
  10857.     self
  10858.         a11: -1.0;        a12: 3.0;        a13: -3.0;    a14: 1.0;
  10859.         a21: 2.0;        a22: -5.0;    a23: 4.0;    a24: -1.0;
  10860.         a31: -1.0;    a32: 0.0;    a33: 1.0;        a34: 0.0;
  10861.         a41: 0.0;        a42: 2.0;    a43: 0.0;    a44: 0.0
  10862. ! !
  10863.  
  10864. !B3DMatrix4x4 methodsFor: 'initialize' stamp: 'ar 2/1/1999 21:27'!
  10865. setCatmullBase
  10866.     "Set the receiver to the Catmull-Rom base matrix"
  10867.     "for further information see:
  10868.         Foley, van Dam, Feiner, Hughes
  10869.         'Computer Graphics: Principles and Practice'
  10870.         Addison-Wesley Publishing Company
  10871.         Second Edition, pp. 505"
  10872.     self
  10873.         a11: -0.5;    a12: 1.5;        a13: -1.5;    a14: 0.5;
  10874.         a21: 1.0;        a22: -2.5;    a23: 2.0;    a24: -0.5;
  10875.         a31: -0.5;    a32: 0.0;    a33: 0.5;    a34: 0.0;
  10876.         a41: 0.0;        a42: 1.0;        a43: 0.0;    a44: 0.0
  10877. ! !
  10878.  
  10879. !B3DMatrix4x4 methodsFor: 'initialize'!
  10880. setIdentity
  10881.     "Set the receiver to the identity matrix"
  10882.     self loadFrom: B3DIdentityMatrix! !
  10883.  
  10884. !B3DMatrix4x4 methodsFor: 'initialize' stamp: 'ar 2/1/1999 21:27'!
  10885. setPolylineBase
  10886.     "Set the receiver to the polyline base matrix :)"
  10887.     self
  10888.         a11: 0.0;        a12: 0.0;        a13: 0.0;        a14: 0.0;
  10889.         a21: 0.0;        a22: 0.0;    a23: 0.0;    a24: 0.0;
  10890.         a31: 0.0;        a32: -1.0;    a33: 1.0;        a34: 0.0;
  10891.         a41: 0.0;        a42: 1.0;        a43: 0.0;    a44: 0.0
  10892. ! !
  10893.  
  10894. !B3DMatrix4x4 methodsFor: 'initialize' stamp: 'ar 2/15/1999 02:55'!
  10895. setScale: aVector
  10896.     self 
  10897.         a11: aVector x;
  10898.         a22: aVector y;
  10899.         a33: aVector z! !
  10900.  
  10901. !B3DMatrix4x4 methodsFor: 'initialize'!
  10902. setTranslation: aVector
  10903.     self 
  10904.         a14: aVector x;
  10905.         a24: aVector y;
  10906.         a34: aVector z! !
  10907.  
  10908. !B3DMatrix4x4 methodsFor: 'initialize'!
  10909. setZero
  10910.     "Set the receiver to the zero matrix"
  10911.     self loadFrom: B3DZeroMatrix! !
  10912.  
  10913. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  10914. a11
  10915.     "Return the element a11"
  10916.     ^self at: 1! !
  10917.  
  10918. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  10919. a11: aNumber
  10920.     "Store the element a11"
  10921.     self at: 1 put: aNumber! !
  10922.  
  10923. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  10924. a12
  10925.     "Return the element a12"
  10926.     ^self at: 2! !
  10927.  
  10928. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  10929. a12: aNumber
  10930.     "Store the element a12"
  10931.     self at: 2 put: aNumber! !
  10932.  
  10933. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  10934. a13
  10935.     "Return the element a13"
  10936.     ^self at: 3! !
  10937.  
  10938. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  10939. a13: aNumber
  10940.     "Store the element a13"
  10941.     self at: 3 put: aNumber! !
  10942.  
  10943. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  10944. a14
  10945.     "Return the element a14"
  10946.     ^self at: 4! !
  10947.  
  10948. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  10949. a14: aNumber
  10950.     "Store the element a14"
  10951.     self at: 4 put: aNumber! !
  10952.  
  10953. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  10954. a21
  10955.     "Return the element a21"
  10956.     ^self at: 5! !
  10957.  
  10958. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  10959. a21: aNumber
  10960.     "Store the element a21"
  10961.     self at: 5 put: aNumber! !
  10962.  
  10963. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  10964. a22
  10965.     "Return the element a22"
  10966.     ^self at: 6! !
  10967.  
  10968. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  10969. a22: aNumber
  10970.     "Store the element a22"
  10971.     self at: 6 put: aNumber! !
  10972.  
  10973. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  10974. a23
  10975.     "Return the element a23"
  10976.     ^self at: 7! !
  10977.  
  10978. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  10979. a23: aNumber
  10980.     "Store the element a23"
  10981.     self at: 7 put: aNumber! !
  10982.  
  10983. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  10984. a24
  10985.     "Return the element a24"
  10986.     ^self at: 8! !
  10987.  
  10988. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  10989. a24: aNumber
  10990.     "Store the element a24"
  10991.     self at: 8 put: aNumber! !
  10992.  
  10993. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  10994. a31
  10995.     "Return the element a31"
  10996.     ^self at: 9! !
  10997.  
  10998. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  10999. a31: aNumber
  11000.     "Store the element a31"
  11001.     self at: 9 put: aNumber! !
  11002.  
  11003. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  11004. a32
  11005.     "Return the element a32"
  11006.     ^self at: 10! !
  11007.  
  11008. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  11009. a32: aNumber
  11010.     "Store the element a32"
  11011.     self at: 10 put: aNumber! !
  11012.  
  11013. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  11014. a33
  11015.     "Return the element a33"
  11016.     ^self at: 11! !
  11017.  
  11018. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  11019. a33: aNumber
  11020.     "Store the element a33"
  11021.     self at: 11 put: aNumber! !
  11022.  
  11023. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  11024. a34
  11025.     "Return the element a34"
  11026.     ^self at: 12! !
  11027.  
  11028. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  11029. a34: aNumber
  11030.     "Store the element a34"
  11031.     self at: 12 put: aNumber! !
  11032.  
  11033. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  11034. a41
  11035.     "Return the element a41"
  11036.     ^self at: 13! !
  11037.  
  11038. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  11039. a41: aNumber
  11040.     "Store the element a41"
  11041.     self at: 13 put: aNumber! !
  11042.  
  11043. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  11044. a42
  11045.     "Return the element a42"
  11046.     ^self at: 14! !
  11047.  
  11048. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  11049. a42: aNumber
  11050.     "Store the element a42"
  11051.     self at: 14 put: aNumber! !
  11052.  
  11053. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  11054. a43
  11055.     "Return the element a43"
  11056.     ^self at: 15! !
  11057.  
  11058. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  11059. a43: aNumber
  11060.     "Store the element a43"
  11061.     self at: 15 put: aNumber! !
  11062.  
  11063. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:29'!
  11064. a44
  11065.     "Return the element a44"
  11066.     ^self at: 16! !
  11067.  
  11068. !B3DMatrix4x4 methodsFor: 'element-access' stamp: 'ar 2/1/1999 21:28'!
  11069. a44: aNumber
  11070.     "Store the element a44"
  11071.     self at: 16 put: aNumber! !
  11072.  
  11073. !B3DMatrix4x4 methodsFor: 'accessing' stamp: 'jsp 2/25/1999 13:58'!
  11074. alternateRotation
  11075.     "Return the angular rotation around each axis of the matrix"
  11076.  
  11077.     | cp sp cy sy cr sr vAngles |
  11078.  
  11079.     vAngles _ B3DVector3 new.
  11080.  
  11081.     ((self a13) = 0) ifTrue: [ ((self a33) >= 0)  ifTrue: [ vAngles at: 2 put: 0.
  11082.                                                       cr _ (self a11).
  11083.                                                       sr _ (self a12).
  11084.                                                       cp _ (self a33). ]
  11085.                                              ifFalse: [ vAngles at: 2 put: (Float pi).
  11086.                                                         cr _ (self a11) negated.
  11087.                                                         sr _ (self a12) negated.
  11088.                                                         cp _ (self a33) negated. ]
  11089.                             ]
  11090.                     ifFalse: [
  11091.                                 vAngles at: 2 put: (((self a13) negated) arcTan: (self a33)).
  11092.                                 cy _ (vAngles at: 3) cos.
  11093.                                 sy _ (vAngles at: 3) sin.
  11094.                                 cr _ (cy * (self a11)) + (sy * (self a31)).
  11095.                                 sr _ (cy* (self a12)) + (sy * (self a32)).
  11096.                                 cp _ (cy * (self a33)) - (sy * (self a13)).
  11097.                             ].
  11098.  
  11099.     sp _ (self a23).
  11100.  
  11101.     vAngles at: 1 put: (sp arcTan: cp).
  11102.     vAngles at: 3 put: (sr arcTan: cr).
  11103.  
  11104.     vAngles at: 1 put: ((vAngles at: 1) radiansToDegrees).
  11105.     vAngles at: 2 put: ((vAngles at: 2) radiansToDegrees).
  11106.     vAngles at: 3 put: ((vAngles at: 3) radiansToDegrees).
  11107.  
  11108.     ^ vAngles.
  11109. ! !
  11110.  
  11111. !B3DMatrix4x4 methodsFor: 'accessing' stamp: 'jsp 2/11/1999 14:09'!
  11112. at: i at: j
  11113.     ^ self at: ((i - 1) * 4 + j).
  11114. ! !
  11115.  
  11116. !B3DMatrix4x4 methodsFor: 'accessing' stamp: 'jsp 2/11/1999 14:09'!
  11117. at: i at: j put: aValue
  11118.     ^ self at: ((i - 1) * 4 + j) put: aValue.
  11119. ! !
  11120.  
  11121. !B3DMatrix4x4 methodsFor: 'accessing' stamp: 'jsp 2/25/1999 13:58'!
  11122. rotation
  11123.     "Return the angular rotation around each axis of the matrix"
  11124.  
  11125.     | vRow1 vRow2 vRow3 vScale vShear vAngles vRowCross determinate |
  11126.  
  11127.     vRow1 _ self row1.
  11128.     vRow2 _ self row2.
  11129.     vRow3 _ self row3.
  11130.  
  11131.     vScale _ B3DVector3 new.
  11132.     vShear _ B3DVector3 new.
  11133.     vAngles _ B3DVector3 new.
  11134.  
  11135.     vScale at: 1 put: (vRow1 length).
  11136.     vRow1 normalize.
  11137.     vShear at: 1 put: (vRow1 dot: vRow2).
  11138.     vRow2 _ vRow2 + (vRow1 * ((vShear at: 1) negated)).
  11139.  
  11140.     vScale at: 2 put: (vRow2 length).
  11141.     vRow2 normalize.
  11142.     vShear at: 1 put: ((vShear at: 1) / (vScale at: 2)).
  11143.  
  11144.     vShear at: 2 put: (vRow1 dot: vRow3).
  11145.     vRow3 _ vRow3 + (vRow1 * ((vShear at: 2) negated)).
  11146.  
  11147.     vShear at: 3 put: (vRow2 dot: vRow3).
  11148.     vRow3 _ vRow3 + (vRow2 * ((vShear at: 3) negated)).
  11149.  
  11150.     vScale at: 3 put: (vRow3 length).
  11151.     vRow3 normalize.
  11152.  
  11153.     vShear at: 2 put: ((vShear at: 2) / (vScale at: 3)).
  11154.     vShear at: 3 put: ((vShear at: 3) / (vScale at: 3)).
  11155.  
  11156.     vRowCross _ vRow2 cross: vRow3.
  11157.     determinate _ vRow1 dot: vRowCross.
  11158.  
  11159.     (determinate < 0.0) ifTrue: [ vRow1 _ vRow1 negated.
  11160.                                 vRow2 _ vRow2 negated.
  11161.                                 vRow3 _ vRow3 negated.
  11162.                                 vScale _ vScale negated. ].
  11163.  
  11164.     vAngles at: 2 put: ((vRow1 at: 3) negated) arcSin.
  11165.  
  11166.     (((vAngles at: 2) cos) ~= 0.0) 
  11167.                                 ifTrue: [ vAngles at: 1 put:
  11168.                                                 ((vRow2 at: 3) arcTan: (vRow3 at: 3)).
  11169.                                           vAngles at: 3 put:
  11170.                                                 ((vRow1 at: 2) arcTan: (vRow1 at: 1)). ]
  11171.                                 ifFalse: [ vAngles at: 1 put:
  11172.                                                 ((vRow2 at: 1) arcTan: (vRow2 at: 2)).
  11173.                                           vAngles at: 3 put: 0.0 ].
  11174.  
  11175.  
  11176.     vAngles at: 1 put: ((vAngles at: 1) radiansToDegrees).
  11177.     vAngles at: 2 put: ((vAngles at: 2) radiansToDegrees).
  11178.     vAngles at: 3 put: ((vAngles at: 3) radiansToDegrees).
  11179.  
  11180.     ^ vAngles.
  11181. ! !
  11182.  
  11183. !B3DMatrix4x4 methodsFor: 'accessing' stamp: 'jsp 2/24/1999 09:46'!
  11184. rotation: aVector
  11185.     | xRot yRot zRot cosPitch sinPitch cosYaw sinYaw cosRoll sinRoll |
  11186.  
  11187.     xRot _ (aVector x) degreesToRadians.
  11188.     yRot _ (aVector y) degreesToRadians.
  11189.     zRot _ (aVector z) degreesToRadians.
  11190.  
  11191.     cosPitch _ xRot cos.
  11192.     sinPitch _ xRot sin.
  11193.     cosYaw _ yRot cos.
  11194.     sinYaw _ yRot sin.
  11195.     cosRoll _ zRot cos.
  11196.     sinRoll _ zRot sin.
  11197.  
  11198.     self a11: (cosRoll*cosYaw).
  11199.     self a12: (sinRoll*cosYaw).
  11200.     self a13: (sinYaw negated).
  11201.  
  11202.     self a21: ((cosRoll*sinYaw*sinPitch) - (sinRoll*cosPitch)).
  11203.     self a22: ((cosRoll*cosPitch) + (sinRoll*sinYaw*sinPitch)).
  11204.     self a23: (cosYaw*sinPitch).
  11205.     self a31: ((cosRoll*sinYaw*cosPitch) + (sinRoll*sinPitch)).
  11206.     self a32: ((sinRoll*sinYaw*cosPitch) - (cosRoll*sinPitch)).
  11207.     self a33: (cosYaw*cosPitch).
  11208.  
  11209.     ^ self.
  11210. ! !
  11211.  
  11212. !B3DMatrix4x4 methodsFor: 'accessing'!
  11213. rotation: anAngle around: aVector3
  11214.     "set up a rotation matrix around the direction aVector3"
  11215.  
  11216.     self loadFrom: (B3DRotation angle: anAngle axis: aVector3) asMatrix4x4! !
  11217.  
  11218. !B3DMatrix4x4 methodsFor: 'accessing'!
  11219. rotation: anAngle aroundX: xValue y: yValue z: zValue
  11220.     "set up a rotation matrix around the direction x/y/z"
  11221.     ^self rotation: anAngle around:(B3DVector3 with: xValue with: yValue with: zValue)! !
  11222.  
  11223. !B3DMatrix4x4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:34'!
  11224. rotationAroundX: anAngle
  11225.     | rad s c |
  11226.     rad := anAngle degreesToRadians.
  11227.     s := rad sin.
  11228.     c := rad cos.
  11229.     self a22: c.
  11230.     self a23: s negated.
  11231.     self a33: c.
  11232.     self a32: s.
  11233.     ^self! !
  11234.  
  11235. !B3DMatrix4x4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:34'!
  11236. rotationAroundY: anAngle
  11237.     | rad s c |
  11238.     rad := anAngle degreesToRadians.
  11239.     s := rad sin.
  11240.     c := rad cos.
  11241.     self a11: c.
  11242.     self a13: s.
  11243.     self a33: c.
  11244.     self a31: s negated.
  11245.     ^self! !
  11246.  
  11247. !B3DMatrix4x4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:35'!
  11248. rotationAroundZ: anAngle
  11249.     | rad s c |
  11250.     rad := anAngle degreesToRadians.
  11251.     s := rad sin.
  11252.     c := rad cos.
  11253.     self a11: c.
  11254.     self a12: s negated.
  11255.     self a22: c.
  11256.     self a21: s.
  11257.     ^self! !
  11258.  
  11259. !B3DMatrix4x4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:35'!
  11260. scaling: aVector
  11261.  
  11262.     ^self scalingX: aVector x y: aVector y z: aVector z! !
  11263.  
  11264. !B3DMatrix4x4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:35'!
  11265. scalingX: xValue y: yValue z: zValue
  11266.  
  11267.     self a11: xValue.
  11268.     self a22: yValue.
  11269.     self a33: zValue.
  11270.     ^self! !
  11271.  
  11272. !B3DMatrix4x4 methodsFor: 'accessing' stamp: 'ar 4/16/1999 21:51'!
  11273. squaredDistanceFrom: aMatrix
  11274.     | sum |
  11275.     sum _ 0.0.
  11276.     1 to: 4 do:[:i|
  11277.         1 to: 4 do:[:j|
  11278.             sum _ sum + ((self at: i at: j) - (aMatrix at: i at: j)) squared]].
  11279.     ^sum! !
  11280.  
  11281. !B3DMatrix4x4 methodsFor: 'accessing'!
  11282. translation
  11283.  
  11284.     ^(B3DVector3 x: self a14 y: self a24 z: self a34)! !
  11285.  
  11286. !B3DMatrix4x4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:36'!
  11287. translation: aVector
  11288.  
  11289.     ^self translationX: aVector x y: aVector y z: aVector z! !
  11290.  
  11291. !B3DMatrix4x4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:36'!
  11292. translationX: xValue y: yValue z: zValue
  11293.  
  11294.     self a14: xValue.
  11295.     self a24: yValue.
  11296.     self a34: zValue.
  11297.     ^self! !
  11298.  
  11299. !B3DMatrix4x4 methodsFor: 'accessing' stamp: 'jsp 2/25/1999 13:58'!
  11300. trotation
  11301.     "Return the angular rotation around each axis of the matrix"
  11302.  
  11303.     | cp sp cy sy cr sr vAngles |
  11304.  
  11305.     vAngles _ B3DVector3 new.
  11306.  
  11307.     ((self a13) = 0) ifTrue: [ ((self a33) >= 0)  ifTrue: [ vAngles at: 2 put: 0.
  11308.                                                       cr _ (self a11).
  11309.                                                       sr _ (self a12).
  11310.                                                       cp _ (self a33). ]
  11311.                                              ifFalse: [ vAngles at: 2 put: (Float pi).
  11312.                                                         cr _ (self a11) negated.
  11313.                                                         sr _ (self a12) negated.
  11314.                                                         cp _ (self a33) negated. ]
  11315.                             ]
  11316.                     ifFalse: [
  11317.                                 vAngles at: 2 put: (((self a13) negated) arcTan: (self a33)).
  11318.                                 cy _ (vAngles at: 3) cos.
  11319.                                 sy _ (vAngles at: 3) sin.
  11320.                                 cr _ (cy * (self a11)) + (sy * (self a31)).
  11321.                                 sr _ (cy* (self a12)) + (sy * (self a32)).
  11322.                                 cp _ (cy * (self a33)) - (sy * (self a13)).
  11323.                             ].
  11324.  
  11325.     sp _ (self a23).
  11326.  
  11327.     vAngles at: 1 put: (sp arcTan: cp).
  11328.     vAngles at: 3 put: (sr arcTan: cr).
  11329.  
  11330.     vAngles at: 1 put: ((vAngles at: 1) radiansToDegrees).
  11331.     vAngles at: 2 put: ((vAngles at: 2) radiansToDegrees).
  11332.     vAngles at: 3 put: ((vAngles at: 3) radiansToDegrees).
  11333.  
  11334.     ^ vAngles.
  11335. ! !
  11336.  
  11337. !B3DMatrix4x4 methodsFor: 'arithmetic' stamp: 'ar 2/1/1999 21:39'!
  11338. + aB3DMatrix
  11339.     "Optimized for Matrix/Matrix operations"
  11340.     <primitive: 'primitiveFloatArrayAddFloatArray'>
  11341.     ^super + aB3DMatrix! !
  11342.  
  11343. !B3DMatrix4x4 methodsFor: 'arithmetic' stamp: 'ar 2/1/1999 21:39'!
  11344. - aB3DMatrix
  11345.     "Optimized for Matrix/Matrix operations"
  11346.     <primitive: 'primitiveFloatArraySubFloatArray'>
  11347.     ^super - aB3DMatrix! !
  11348.  
  11349. !B3DMatrix4x4 methodsFor: 'transforming' stamp: 'jsp 2/9/1999 17:22'!
  11350. composeWith: m2
  11351.     "Perform a 4x4 matrix multiplication."
  11352.  
  11353.     | c1 c2 c3 c4 m3 |
  11354.     m3 _ B3DMatrix4x4 new.
  11355.  
  11356.     c1 _ ((self a11 * m2 a11) + (self a12 * m2 a21) + 
  11357.                 (self a13 * m2 a31) + (self a14 * m2 a41)).
  11358.     c2 _ ((self a11 * m2 a12) + (self a12 * m2 a22) + 
  11359.                 (self a13 * m2 a32) + (self a14 * m2 a42)).
  11360.     c3 _ ((self a11 * m2 a13) + (self a12 * m2 a23) + 
  11361.                 (self a13 * m2 a33) + (self a14 * m2 a43)).
  11362.     c4 _ ((self a11 * m2 a14) + (self a12 * m2 a24) + 
  11363.                 (self a13 * m2 a34) + (self a14 * m2 a44)).
  11364.  
  11365.     m3 a11: c1; a12: c2; a13: c3; a14: c4.
  11366.  
  11367.     c1 _ ((self a21 * m2 a11) + (self a22 * m2 a21) + 
  11368.                 (self a23 * m2 a31) + (self a24 * m2 a41)).
  11369.     c2 _ ((self a21 * m2 a12) + (self a22 * m2 a22) + 
  11370.                 (self a23 * m2 a32) + (self a24 * m2 a42)).
  11371.     c3 _ ((self a21 * m2 a13) + (self a22 * m2 a23) + 
  11372.                 (self a23 * m2 a33) + (self a24 * m2 a43)).
  11373.     c4 _ ((self a21 * m2 a14) + (self a22 * m2 a24) + 
  11374.                 (self a23 * m2 a34) + (self a24 * m2 a44)).
  11375.  
  11376.     m3 a21: c1; a22: c2; a23: c3; a24: c4.
  11377.  
  11378.     c1 _ ((self a31 * m2 a11) + (self a32 * m2 a21) + 
  11379.                 (self a33 * m2 a31) + (self a34 * m2 a41)).
  11380.     c2 _ ((self a31 * m2 a12) + (self a32 * m2 a22) + 
  11381.                 (self a33 * m2 a32) + (self a34 * m2 a42)).
  11382.     c3 _ ((self a31 * m2 a13) + (self a32 * m2 a23) + 
  11383.                 (self a33 * m2 a33) + (self a34 * m2 a43)).
  11384.     c4 _ ((self a31 * m2 a14) + (self a32 * m2 a24) + 
  11385.                 (self a33 * m2 a34) + (self a34 * m2 a44)).
  11386.  
  11387.     m3 a31: c1; a32: c2; a33: c3; a34: c4.
  11388.  
  11389.     c1 _ ((self a41 * m2 a11) + (self a42 * m2 a21) + 
  11390.                 (self a43 * m2 a31) + (self a44 * m2 a41)).
  11391.     c2 _ ((self a41 * m2 a12) + (self a42 * m2 a22) + 
  11392.                 (self a43 * m2 a32) + (self a44 * m2 a42)).
  11393.     c3 _ ((self a41 * m2 a13) + (self a42 * m2 a23) + 
  11394.                 (self a43 * m2 a33) + (self a44 * m2 a43)).
  11395.     c4 _ ((self a41 * m2 a14) + (self a42 * m2 a24) + 
  11396.                 (self a43 * m2 a34) + (self a44 * m2 a44)).
  11397.  
  11398.     m3 a41: c1; a42: c2; a43: c3; a44: c4.
  11399.  
  11400.     ^m3! !
  11401.  
  11402. !B3DMatrix4x4 methodsFor: 'transforming' stamp: 'ar 2/15/1999 23:56'!
  11403. composedWithGlobal: aB3DMatrix4x4
  11404.     | result |
  11405.     result _ self class new.
  11406.     self privateTransformMatrix: aB3DMatrix4x4 with: self into: result.
  11407.     ^result! !
  11408.  
  11409. !B3DMatrix4x4 methodsFor: 'transforming' stamp: 'ar 2/15/1999 23:57'!
  11410. composedWithLocal: aB3DMatrix4x4
  11411.     | result |
  11412.     result _ self class new.
  11413.     self privateTransformMatrix: self with: aB3DMatrix4x4 into: result.
  11414.     ^result! !
  11415.  
  11416. !B3DMatrix4x4 methodsFor: 'transforming' stamp: 'ar 5/21/2000 16:34'!
  11417. inverseTransformation
  11418.     "Return the inverse matrix of the receiver."
  11419.     ^self clone inplaceHouseHolderInvert.! !
  11420.  
  11421. !B3DMatrix4x4 methodsFor: 'transforming' stamp: 'ar 2/15/1999 23:50'!
  11422. localPointToGlobal: aVector
  11423.     "Multiply aVector (temporarily converted to 4D) with the receiver"
  11424.     | x y z rx ry rz rw |
  11425.     x := aVector x.
  11426.     y := aVector y.
  11427.     z := aVector z.
  11428.  
  11429.     rx := (x * self a11) + (y * self a12) + (z * self a13) + self a14.
  11430.     ry := (x * self a21) + (y * self a22) + (z * self a23) + self a24.
  11431.     rz := (x * self a31) + (y * self a32) + (z * self a33) + self a34.
  11432.     rw := (x * self a41) + (y * self a42) + (z * self a43) + self a44.
  11433.  
  11434.     ^B3DVector3 x:(rx/rw) y: (ry/rw) z: (rz/rw)! !
  11435.  
  11436. !B3DMatrix4x4 methodsFor: 'transforming' stamp: 'ar 2/7/1999 06:32'!
  11437. quickTransformV3ArrayFrom: srcArray to: dstArray
  11438.     "Transform the 3 element vertices from srcArray to dstArray.
  11439.     ASSUMPTION: a41 = a42 = a43 = 0.0 and a44 = 1.0"
  11440.     | a11 a12 a13 a14 a21 a22 a23 a24 a31 a32 a33 a34 x y z index |
  11441.     self flag: #b3dPrimitive.
  11442.     a11 _ self a11.    a12 _ self a12.    a13 _ self a13.    a14 _ self a14.
  11443.     a21 _ self a21.    a22 _ self a22.    a23 _ self a23.    a24 _ self a24.
  11444.     a31 _ self a31.    a32 _ self a32.    a33 _ self a33.    a34 _ self a34.
  11445.     1 to: srcArray size do:[:i|
  11446.         index _ i-1*3.
  11447.         x _ srcArray floatAt: index+1.
  11448.         y _ srcArray floatAt: index+2.
  11449.         z _ srcArray floatAt: index+3.
  11450.         dstArray floatAt: index+1 put: (a11*x) + (a12*y) + (a13*z) + a14.
  11451.         dstArray floatAt: index+2 put: (a21*x) + (a22*y) + (a23*z) + a24.
  11452.         dstArray floatAt: index+3 put: (a31*x) + (a32*y) + (a33*z) + a34.
  11453.     ].
  11454.     ^dstArray! !
  11455.  
  11456. !B3DMatrix4x4 methodsFor: 'transforming' stamp: 'ar 2/1/1999 21:42'!
  11457. transposed
  11458.     "Return a transposed copy of the receiver"
  11459.     | matrix |
  11460.     matrix := self class new.
  11461.     matrix 
  11462.         a11: self a11; a12: self a21; a13: self a31; a14: self a41;
  11463.         a21: self a12; a22: self a22; a23: self a32; a24: self a42;
  11464.         a31: self a13; a32: self a23; a33: self a33; a34: self a43;
  11465.         a41: self a14; a42: self a24; a43: self a34; a44: self a44.
  11466.     ^matrix! !
  11467.  
  11468. !B3DMatrix4x4 methodsFor: 'double dispatching' stamp: 'ar 2/1/1999 21:49'!
  11469. printOn: aStream
  11470.     "Print the receiver on aStream"
  11471.     1 to: 4 do:[:r|
  11472.         1 to: 4 do:[:c| 
  11473.             (self at: r-1*4+c) printOn: aStream.
  11474.             aStream nextPut: Character space].
  11475.         (r < 4) ifTrue:[aStream nextPut: Character cr]].! !
  11476.  
  11477. !B3DMatrix4x4 methodsFor: 'double dispatching' stamp: 'ar 2/8/1999 20:11'!
  11478. productFromMatrix4x4: matrix
  11479.     "Multiply a 4x4 matrix with the receiver."
  11480.     | result |
  11481.     result := self class new.
  11482.     result a11: ((matrix a11 * self a11) + (matrix a12 * self a21) + 
  11483.                 (matrix a13 * self a31) + (matrix a14 * self a41)).
  11484.     result a12: ((matrix a11 * self a12) + (matrix a12 * self a22) + 
  11485.                 (matrix a13 * self a32) + (matrix a14 * self a42)).
  11486.     result a13: ((matrix a11 * self a13) + (matrix a12 * self a23) + 
  11487.                 (matrix a13 * self a33) + (matrix a14 * self a43)).
  11488.     result a14: ((matrix a11 * self a14) + (matrix a12 * self a24) + 
  11489.                 (matrix a13 * self a34) + (matrix a14 * self a44)).
  11490.  
  11491.     result a21: ((matrix a21 * self a11) + (matrix a22 * self a21) + 
  11492.                 (matrix a23 * self a31) + (matrix a24 * self a41)).
  11493.     result a22: ((matrix a21 * self a12) + (matrix a22 * self a22) + 
  11494.                 (matrix a23 * self a32) + (matrix a24 * self a42)).
  11495.     result a23: ((matrix a21 * self a13) + (matrix a22 * self a23) + 
  11496.                 (matrix a23 * self a33) + (matrix a24 * self a43)).
  11497.     result a24: ((matrix a21 * self a14) + (matrix a22 * self a24) + 
  11498.                 (matrix a23 * self a34) + (matrix a24 * self a44)).
  11499.  
  11500.     result a31: ((matrix a31 * self a11) + (matrix a32 * self a21) + 
  11501.                 (matrix a33 * self a31) + (matrix a34 * self a41)).
  11502.     result a32: ((matrix a31 * self a12) + (matrix a32 * self a22) + 
  11503.                 (matrix a33 * self a32) + (matrix a34 * self a42)).
  11504.     result a33: ((matrix a31 * self a13) + (matrix a32 * self a23) + 
  11505.                 (matrix a33 * self a33) + (matrix a34 * self a43)).
  11506.     result a34: ((matrix a31 * self a14) + (matrix a32 * self a24) + 
  11507.                 (matrix a33 * self a34) + (matrix a34 * self a44)).
  11508.  
  11509.     result a41: ((matrix a41 * self a11) + (matrix a42 * self a21) + 
  11510.                 (matrix a43 * self a31) + (matrix a44 * self a41)).
  11511.     result a42: ((matrix a41 * self a12) + (matrix a42 * self a22) + 
  11512.                 (matrix a43 * self a32) + (matrix a44 * self a42)).
  11513.     result a43: ((matrix a41 * self a13) + (matrix a42 * self a23) + 
  11514.                 (matrix a43 * self a33) + (matrix a44 * self a43)).
  11515.     result a44: ((matrix a41 * self a14) + (matrix a42 * self a24) + 
  11516.                 (matrix a43 * self a34) + (matrix a44 * self a44)).
  11517.  
  11518.     ^result! !
  11519.  
  11520. !B3DMatrix4x4 methodsFor: 'double dispatching'!
  11521. productFromVector3: aVector3
  11522.     "Multiply aVector (temporarily converted to 4D) with the receiver"
  11523.     | x y z rx ry rz rw |
  11524.     x := aVector3 x.
  11525.     y := aVector3 y.
  11526.     z := aVector3 z.
  11527.  
  11528.     rx := (x * self a11) + (y * self a21) + (z * self a31) + self a41.
  11529.     ry := (x * self a12) + (y * self a22) + (z * self a32) + self a42.
  11530.     rz := (x * self a13) + (y * self a23) + (z * self a33) + self a43.
  11531.     rw := (x * self a14) + (y * self a24) + (z * self a34) + self a44.
  11532.  
  11533.     ^B3DVector3 x:(rx/rw) y: (ry/rw) z: (rz/rw)! !
  11534.  
  11535. !B3DMatrix4x4 methodsFor: 'double dispatching'!
  11536. productFromVector4: aVector4
  11537.     "Multiply aVector with the receiver"
  11538.     | x y z w rx ry rz rw |
  11539.     x := aVector4 x.
  11540.     y := aVector4 y.
  11541.     z := aVector4 z.
  11542.     w := aVector4 w.
  11543.  
  11544.     rx := (x * self a11) + (y * self a21) + (z * self a31) + (w * self a41).
  11545.     ry := (x * self a12) + (y * self a22) + (z * self a32) + (w * self a42).
  11546.     rz := (x * self a13) + (y * self a23) + (z * self a33) + (w * self a43).
  11547.     rw := (x * self a14) + (y * self a24) + (z * self a34) + (w * self a44).
  11548.  
  11549.     ^B3DVector4 x:rx y: ry z: rz w: rw! !
  11550.  
  11551. !B3DMatrix4x4 methodsFor: 'solving' stamp: 'ar 2/1/1999 21:50'!
  11552. inplaceDecomposeLU
  11553.     "Decompose the receiver in place by using gaussian elimination w/o pivot search"
  11554.     | x |
  11555.     1 to: 4 do:[:j|
  11556.         "i-th equation (row)"
  11557.         j+1 to: 4 do:[:i|
  11558.             x := (self at: i at: j) / (self at: j at: j).
  11559.             j to: 4 do:[:k|
  11560.                 self at: i at: k put: (self at: i at: k) - ((self at: j at: k) * x)].
  11561.             self at: i at: j put: x]].
  11562. ! !
  11563.  
  11564. !B3DMatrix4x4 methodsFor: 'solving' stamp: 'ar 5/22/2000 17:13'!
  11565. inplaceHouseHolderInvert
  11566.     "Solve the linear equation self * aVector = x by using HouseHolder's transformation.
  11567.     Note: This scheme is numerically better than using gaussian elimination even though it takes
  11568.     somewhat longer"
  11569.     | d x sigma beta sum s|
  11570.     <primitive:'b3dInplaceHouseHolderInvert' module:'Squeak3D'>
  11571.     x _ B3DMatrix4x4 identity.
  11572.     d _ B3DMatrix4x4 new.
  11573.     1 to: 4 do:[:j|
  11574.         sigma := 0.0.
  11575.         j to: 4 do:[:i| sigma := sigma + ((self at: i at: j) squared)].
  11576.         sigma isZero ifTrue:[^nil]. "matrix is singular"
  11577.         ((self at: j at: j) < 0.0) 
  11578.             ifTrue:[ s:= sigma sqrt]
  11579.             ifFalse:[ s:= sigma sqrt negated].
  11580.         1 to: 4 do:[:r| d at: j at: r put: s].
  11581.         beta := 1.0 / ( s * (self at: j at: j) - sigma).
  11582.         self at: j at: j put: ((self at: j at: j) - s).
  11583.         "update remaining columns"
  11584.         j+1 to: 4 do:[:k|
  11585.             sum := 0.0.
  11586.             j to: 4 do:[:i| sum := sum + ((self at: i at: j) * (self at: i at: k))].
  11587.             sum := sum * beta.
  11588.             j to: 4 do:[:i| 
  11589.                 self at: i at: k put: ((self at: i at: k) + ((self at: i at: j) * sum))]].
  11590.         "update vector"
  11591.         1 to: 4 do:[:r|
  11592.             sum := nil.
  11593.             j to: 4 do:[:i| 
  11594.                 sum := sum isNil 
  11595.                     ifTrue:[(x at: i at: r) * (self at: i at: j)] 
  11596.                     ifFalse:[sum + ((x at: i at: r) * (self at: i at: j))]].
  11597.             sum := sum * beta.
  11598.             j to: 4 do:[:i| 
  11599.                 x at: i at: r put:((x at: i at: r) + (sum * (self at: i at: j)))].
  11600.         ].
  11601.     ].
  11602.     "Now calculate result"
  11603.     1 to: 4 do:[:r|
  11604.         4 to: 1 by: -1 do:[:i|
  11605.             i+1 to: 4 do:[:j|
  11606.                 x at: i at: r put: ((x at: i at: r) - ((x at: j at: r) * (self at: i at: j))) ].
  11607.             x at: i at: r put: ((x at: i at: r) / (d at: i at: r))].
  11608.     ].
  11609.     self loadFrom: x.
  11610.     "Return receiver"! !
  11611.  
  11612. !B3DMatrix4x4 methodsFor: 'solving'!
  11613. inplaceHouseHolderTransform: aVector
  11614.     "Solve the linear equation self * aVector = x by using HouseHolder's transformation.
  11615.     Note: This scheme is numerically better than using gaussian elimination even though it takes
  11616.     somewhat longer"
  11617.     | d x sigma beta sum s|
  11618.     x := Array with: aVector x with: aVector y with: aVector z with: aVector w.
  11619.     d := Array new: 4.
  11620.     1 to: 4 do:[:j|
  11621.         sigma := 0.0.
  11622.         j to: 4 do:[:i| sigma := sigma + ((self at: i at: j) squared)].
  11623.         sigma isZero ifTrue:[^nil]. "matrix is singular"
  11624.         ((self at: j at: j) < 0.0) 
  11625.             ifTrue:[ s:= d at: j put: (sigma sqrt)]
  11626.             ifFalse:[ s:= d at: j put: (sigma sqrt negated)].
  11627.         beta := 1.0 / ( s * (self at: j at: j) - sigma).
  11628.         self at: j at: j put: ((self at: j at: j) - s).
  11629.         "update remaining columns"
  11630.         j+1 to: 4 do:[:k|
  11631.             sum := 0.0.
  11632.             j to: 4 do:[:i| sum := sum + ((self at: i at: j) * (self at: i at: k))].
  11633.             sum := sum * beta.
  11634.             j to: 4 do:[:i| 
  11635.                 self at: i at: k put: ((self at: i at: k) + ((self at: i at: j) * sum))]].
  11636.         "update vector"
  11637.         sum := nil.
  11638.         j to: 4 do:[:i| 
  11639.             sum := sum isNil 
  11640.                 ifTrue:[(x at: i) * (self at: i at: j)] 
  11641.                 ifFalse:[sum + ((x at: i) * (self at: i at: j))]].
  11642.         sum := sum * beta.
  11643.         j to: 4 do:[:i| 
  11644.             x at: i put:((x at: i) + (sum * (self at: i at: j)))].
  11645.     ].
  11646.     "Now calculate result"
  11647.     4 to: 1 by: -1 do:[:i|
  11648.         i+1 to: 4 do:[:j|
  11649.             x at: i put: ((x at: i) - ((x at: j) * (self at: i at: j))) ].
  11650.         x at: i put: ((x at: i) / (d at: i))].
  11651.     ^B3DVector4 x: (x at: 1) y: (x at: 2) z: (x at: 3) w: (x at: 4)
  11652. ! !
  11653.  
  11654. !B3DMatrix4x4 methodsFor: 'solving' stamp: 'ar 2/1/1999 21:52'!
  11655. solve: aVector
  11656.  
  11657.     ^self clone inplaceHouseHolderTransform: aVector
  11658.     "or:
  11659.     ^self clone inplaceDecomposeLU solveLU: aVector
  11660.     "! !
  11661.  
  11662. !B3DMatrix4x4 methodsFor: 'solving'!
  11663. solveLU: aVector
  11664.     "Given a decomposed matrix using gaussian elimination solve the linear equations."
  11665.     | x v |
  11666.     v := Array with: aVector x with: aVector y with: aVector z with: aVector w.
  11667.     "L first"
  11668.     1 to: 4 do:[:i| "Top to bottom"
  11669.         x := 0.0.
  11670.         1 to: i-1 do:[:j|
  11671.             "From left to right w/o diagonal element"
  11672.             x := x + ((v at: j) * (self at: i at: j))].
  11673.         "No need to divide by the diagonal element - this is always 1.0 in L"
  11674.         v at: i put: (v at: i) - x].
  11675.     "Now U"
  11676.     4 to: 1 by: -1 do:[:i| "Bottom to top"
  11677.         x := 0.0.
  11678.         4 to: i+1 by: -1 do:[:j|
  11679.             "From right to left w/o diagonal element"
  11680.             x := x + ((v at: j) * (self at: i at: j))].
  11681.         "Divide by diagonal element"
  11682.         v at: i put: (v at: i) - x / (self at: i at: i)].
  11683.     ^B3DVector4 x: (v at: 1) y: (v at: 2) z: (v at: 3) w: (v at: 4)
  11684. ! !
  11685.  
  11686. !B3DMatrix4x4 methodsFor: 'comparing' stamp: 'ar 2/1/1999 21:53'!
  11687. squaredErrorDistanceTo: anotherMatrix
  11688.     | result temp |
  11689.     result := self - anotherMatrix.
  11690.     temp := 0.
  11691.     1 to: 4 do: [:i | 1 to: 4 do: [:j| temp := temp + ((result at: i-1*4+j) squared)]].
  11692.     ^temp sqrt.! !
  11693.  
  11694. !B3DMatrix4x4 methodsFor: 'testing' stamp: 'ar 2/1/1999 21:54'!
  11695. isIdentity
  11696.     ^self = B3DIdentityMatrix! !
  11697.  
  11698. !B3DMatrix4x4 methodsFor: 'testing' stamp: 'ar 2/1/1999 21:54'!
  11699. isZero
  11700.     ^self = B3DZeroMatrix! !
  11701.  
  11702. !B3DMatrix4x4 methodsFor: 'converting'!
  11703. asMatrix4x4
  11704.     ^self! !
  11705.  
  11706. !B3DMatrix4x4 methodsFor: 'converting' stamp: 'jsp 3/5/1999 15:31'!
  11707. asQuaternion
  11708.     "Convert the matrix to a quaternion"
  11709.  
  11710.     | x y z a a2 x2 y2 a4 |
  11711.  
  11712.     a2 _ 0.25 * (1.0 + (self a11) + (self a22) + (self a33)).
  11713.  
  11714.     (a2 > 0) ifTrue: [
  11715.                         a _ a2 sqrt.
  11716.                         a4 _ 4.0 * a.
  11717.                         x _ ((self a32) - (self a23)) / a4.
  11718.                         y _ ((self a13) - (self a31)) / a4.
  11719.                         z _ ((self a21) - (self a12)) / a4.
  11720.                     ]
  11721.             ifFalse: [
  11722.                         a _ 0.
  11723.                         x2 _ -0.5 * ((self a22) + (self a33)).
  11724.                         (x2 > 0) ifTrue: [
  11725.                                             x _ x2 sqrt.
  11726.                                             x2 _ 2 * x.
  11727.                                             y _ (self a21) / x2.
  11728.                                             z _ (self a31) / x2.
  11729.                                         ]
  11730.                                 ifFalse: [
  11731.                                             x _ 0.
  11732.                                             y2 _ 0.5 * (1.0 - (self a33)).
  11733.                                             (y2 > 0) ifTrue: [
  11734.                                                                 y _ y2 sqrt.
  11735.                                                                 y2 _ 2 * y.
  11736.                                                                 z _ (self a32) / y2.
  11737.                                                             ]
  11738.                                                     ifFalse: [
  11739.                                                                 y _ 0.0.
  11740.                                                                 z _ 1.0.
  11741.                                                             ]
  11742.                                         ]
  11743.                     ].
  11744.  
  11745.     ^ (B3DRotation a: a b: x c: y d: z).
  11746. ! !
  11747.  
  11748. !B3DMatrix4x4 methodsFor: 'private' stamp: 'ar 2/17/1999 04:23'!
  11749. privateTransformMatrix: m1 with: m2 into: m3
  11750.     "Perform a 4x4 matrix multiplication
  11751.         m2 * m1 = m3
  11752.     being equal to first transforming points by m2 and then by m1.
  11753.     Note that m1 may be identical to m3.
  11754.     NOTE: The primitive implementation does NOT return m3 - and so don't we!!"
  11755.     | c1 c2 c3 c4 |
  11756.     m2 == m3 ifTrue:[^self error:'Argument and result matrix identical'].
  11757.     c1 _ ((m1 a11 * m2 a11) + (m1 a12 * m2 a21) + 
  11758.                 (m1 a13 * m2 a31) + (m1 a14 * m2 a41)).
  11759.     c2 _ ((m1 a11 * m2 a12) + (m1 a12 * m2 a22) + 
  11760.                 (m1 a13 * m2 a32) + (m1 a14 * m2 a42)).
  11761.     c3 _ ((m1 a11 * m2 a13) + (m1 a12 * m2 a23) + 
  11762.                 (m1 a13 * m2 a33) + (m1 a14 * m2 a43)).
  11763.     c4 _ ((m1 a11 * m2 a14) + (m1 a12 * m2 a24) + 
  11764.                 (m1 a13 * m2 a34) + (m1 a14 * m2 a44)).
  11765.  
  11766.     m3 a11: c1; a12: c2; a13: c3; a14: c4.
  11767.  
  11768.     c1 _ ((m1 a21 * m2 a11) + (m1 a22 * m2 a21) + 
  11769.                 (m1 a23 * m2 a31) + (m1 a24 * m2 a41)).
  11770.     c2 _ ((m1 a21 * m2 a12) + (m1 a22 * m2 a22) + 
  11771.                 (m1 a23 * m2 a32) + (m1 a24 * m2 a42)).
  11772.     c3 _ ((m1 a21 * m2 a13) + (m1 a22 * m2 a23) + 
  11773.                 (m1 a23 * m2 a33) + (m1 a24 * m2 a43)).
  11774.     c4 _ ((m1 a21 * m2 a14) + (m1 a22 * m2 a24) + 
  11775.                 (m1 a23 * m2 a34) + (m1 a24 * m2 a44)).
  11776.  
  11777.     m3 a21: c1; a22: c2; a23: c3; a24: c4.
  11778.  
  11779.     c1 _ ((m1 a31 * m2 a11) + (m1 a32 * m2 a21) + 
  11780.                 (m1 a33 * m2 a31) + (m1 a34 * m2 a41)).
  11781.     c2 _ ((m1 a31 * m2 a12) + (m1 a32 * m2 a22) + 
  11782.                 (m1 a33 * m2 a32) + (m1 a34 * m2 a42)).
  11783.     c3 _ ((m1 a31 * m2 a13) + (m1 a32 * m2 a23) + 
  11784.                 (m1 a33 * m2 a33) + (m1 a34 * m2 a43)).
  11785.     c4 _ ((m1 a31 * m2 a14) + (m1 a32 * m2 a24) + 
  11786.                 (m1 a33 * m2 a34) + (m1 a34 * m2 a44)).
  11787.  
  11788.     m3 a31: c1; a32: c2; a33: c3; a34: c4.
  11789.  
  11790.     c1 _ ((m1 a41 * m2 a11) + (m1 a42 * m2 a21) + 
  11791.                 (m1 a43 * m2 a31) + (m1 a44 * m2 a41)).
  11792.     c2 _ ((m1 a41 * m2 a12) + (m1 a42 * m2 a22) + 
  11793.                 (m1 a43 * m2 a32) + (m1 a44 * m2 a42)).
  11794.     c3 _ ((m1 a41 * m2 a13) + (m1 a42 * m2 a23) + 
  11795.                 (m1 a43 * m2 a33) + (m1 a44 * m2 a43)).
  11796.     c4 _ ((m1 a41 * m2 a14) + (m1 a42 * m2 a24) + 
  11797.                 (m1 a43 * m2 a34) + (m1 a44 * m2 a44)).
  11798.  
  11799.     m3 a41: c1; a42: c2; a43: c3; a44: c4.! !
  11800.  
  11801. !B3DMatrix4x4 methodsFor: 'row-access' stamp: 'jsp 2/24/1999 17:10'!
  11802. row1
  11803.     "Return row 1"
  11804.  
  11805.     ^ (B3DVector3 x: (self a11) y: (self a12) z: (self a13)).
  11806. ! !
  11807.  
  11808. !B3DMatrix4x4 methodsFor: 'row-access' stamp: 'jsp 2/24/1999 17:11'!
  11809. row2
  11810.     "Return row 2"
  11811.  
  11812.     ^ (B3DVector3 x: (self a21) y: (self a22) z: (self a23)).
  11813. ! !
  11814.  
  11815. !B3DMatrix4x4 methodsFor: 'row-access' stamp: 'jsp 2/24/1999 17:11'!
  11816. row3
  11817.     "Return row 3"
  11818.  
  11819.     ^ (B3DVector3 x: (self a31) y: (self a32) z: (self a33)).
  11820. ! !
  11821.  
  11822. !B3DMatrix4x4 class methodsFor: 'class initialization' stamp: 'ar 2/1/1999 21:58'!
  11823. initialize
  11824.     "B3DMatrix4x4 initialize"
  11825.     B3DZeroMatrix _ self new.
  11826.     B3DIdentityMatrix _ self new.
  11827.     B3DIdentityMatrix a11: 1.0; a22: 1.0; a33: 1.0; a44: 1.0.! !
  11828.  
  11829. !B3DMatrix4x4 class methodsFor: 'instance creation'!
  11830. identity
  11831.     ^self new setIdentity! !
  11832.  
  11833. !B3DMatrix4x4 class methodsFor: 'instance creation' stamp: 'ar 2/1/1999 21:25'!
  11834. numElements
  11835.     ^16! !
  11836.  
  11837. !B3DMatrix4x4 class methodsFor: 'instance creation' stamp: 'ar 2/15/1999 23:58'!
  11838. rotatedBy: angle around: axis centeredAt: origin
  11839.     "Create a matrix rotating points around the given origin using the angle/axis pair"
  11840.     | xform |
  11841.     xform _ self withOffset: origin negated.
  11842.     xform _ xform composedWithGlobal:(B3DRotation angle: angle axis: axis) asMatrix4x4.
  11843.     xform _ xform composedWithGlobal: (self withOffset: origin).
  11844.     ^xform! !
  11845.  
  11846. !B3DMatrix4x4 class methodsFor: 'instance creation' stamp: 'ar 2/15/1999 23:48'!
  11847. withOffset: amount
  11848.     ^self identity setTranslation: amount! !
  11849.  
  11850. !B3DMatrix4x4 class methodsFor: 'instance creation'!
  11851. zero
  11852.     ^self new! !
  11853.  
  11854. !B3DMorph methodsFor: 'initialize' stamp: 'mjg 9/28/1999 10:19'!
  11855. initialize
  11856.     super initialize.
  11857.     geometry _ B3DBox from: (-0.7@-0.7@-0.7) to: (0.7@0.7@0.7).
  11858.     camera _ B3DCamera new.
  11859.     (self confirm:'Put me into a clipping frame?')
  11860.         ifTrue:[camera position: 0@0@1.5]
  11861.         ifFalse:[camera position: 0@0@2. color _ nil].
  11862.     camera nearDistance: 0.1.
  11863.     camera farDistance: 5.0.
  11864.     self extent: 100@100.
  11865.     texture _ (Form extent: 100@100) asTexture.
  11866.     angle _ 0.! !
  11867.  
  11868. !B3DMorph methodsFor: 'drawing' stamp: 'ar 2/8/1999 02:48'!
  11869. drawOn: aCanvas
  11870.     color ifNotNil:["aCanvas frameAndFillRectangle: self bounds fillColor: color borderWidth: 1 borderColor: Color black."
  11871.         aCanvas frameRectangle: self bounds color: self color].
  11872.     aCanvas asBalloonCanvas render: self.
  11873. ! !
  11874.  
  11875. !B3DMorph methodsFor: 'drawing' stamp: 'ar 2/16/1999 17:26'!
  11876. renderOn: aRenderer
  11877.     camera ifNotNil:[
  11878.         aRenderer viewport: (self bounds insetBy: 1@1).
  11879.         aRenderer clearDepthBuffer.
  11880.         aRenderer loadIdentity.
  11881.         camera renderOn: aRenderer].
  11882.     aRenderer texture: texture.
  11883.     aRenderer transformBy: (B3DRotation angle: angle axis: 0@1@0).
  11884.     geometry ifNotNil:[geometry renderOn: aRenderer].! !
  11885.  
  11886. !B3DMorph methodsFor: 'stepping' stamp: 'ar 2/4/1999 20:15'!
  11887. step
  11888.     angle _ angle + 5.
  11889.     self changed.! !
  11890.  
  11891. !B3DMorph methodsFor: 'stepping' stamp: 'ar 2/4/1999 20:15'!
  11892. stepTime
  11893.     ^50! !
  11894.  
  11895. !B3DMorph methodsFor: 'stepping' stamp: 'ar 2/4/1999 20:15'!
  11896. wantsSteps
  11897.     ^true! !
  11898.  
  11899. !B3DMorph methodsFor: 'menu' stamp: 'ar 2/16/1999 17:22'!
  11900. addCustomMenuItems: aCustomMenu hand: aHandMorph
  11901.     super addCustomMenuItems: aCustomMenu hand: aHandMorph.
  11902.     aCustomMenu add:'set texture' action: #setTexture.! !
  11903.  
  11904. !B3DMorph methodsFor: 'menu' stamp: 'ar 2/16/1999 17:28'!
  11905. setTexture
  11906.     | tex |
  11907.     tex _ B3DTexture fromDisplay:(Rectangle originFromUser: 128@128).
  11908.     tex wrap: true.
  11909.     tex interpolate: false.
  11910.     tex envMode: 0.
  11911.     texture _ tex.
  11912.     self changed! !
  11913.  
  11914. The only purpose of this rasterizer is to measure the actual transform/lighting/clipping speed of an engine.!
  11915. !B3DNullRasterizer methodsFor: 'testing' stamp: 'ar 2/16/1999 02:31'!
  11916. needsClip
  11917.     "Yepp. We want to see how well our clipper performs."
  11918.     ^true! !
  11919.  
  11920. !B3DNullRasterizer methodsFor: 'processing' stamp: 'ar 5/26/2000 15:34'!
  11921. clearViewport: aColor
  11922.     "Do nothing"! !
  11923.  
  11924. !B3DNullRasterizer class methodsFor: 'testing' stamp: 'ar 2/16/1999 17:37'!
  11925. isAvailable
  11926.     "Return true if this part of the engine is available"
  11927.     ^true! !
  11928.  
  11929. !B3DPickerEngine methodsFor: 'initialize' stamp: 'ar 4/18/1999 00:21'!
  11930. flush
  11931.     "Ignored"! !
  11932.  
  11933. !B3DPickerEngine methodsFor: 'initialize' stamp: 'ar 6/2/1999 12:08'!
  11934. initialize
  11935.     "Do not call super initialize here. We get our components directly by the creating engine."
  11936.     pickList _ SortedCollection new: 100.
  11937.     pickList sortBlock:[:a1 :a2| a1 value rasterPosZ < a2 value rasterPosZ].
  11938.     objects _ OrderedCollection new: 100.
  11939.     objects resetTo: 1.
  11940.     maxVtx _ B3DPrimitiveVertex new.
  11941.     maxVtx rasterPosZ: 1.0e30.
  11942.     maxVtx rasterPosW: 1.0.! !
  11943.  
  11944. !B3DPickerEngine methodsFor: 'initialize' stamp: 'ar 4/17/1999 23:11'!
  11945. loadFrom: aRenderEngine
  11946.     "Load our components from the given render engine.
  11947.     The idea is that all of the state is shared so that transformations
  11948.     send during picking will be preserved in the given render engine."
  11949.     vertexBuffer _ aRenderEngine getVertexBuffer.
  11950.     transformer _ aRenderEngine getTransformer.
  11951.     shader _ aRenderEngine getShader.
  11952.     clipper _ aRenderEngine getClipper.
  11953.     rasterizer _ aRenderEngine getRasterizer. ! !
  11954.  
  11955. !B3DPickerEngine methodsFor: 'picking' stamp: 'ar 4/18/1999 02:25'!
  11956. pickAt: aPoint extent: extentPoint
  11957.     "Initialize the receiver for picking at the given point using the given extent."
  11958.     pickMatrix _ self pickingMatrixAt: aPoint extent: extentPoint.! !
  11959.  
  11960. !B3DPickerEngine methodsFor: 'picking' stamp: 'ar 6/2/1999 12:03'!
  11961. render: anObject
  11962.     | assoc |
  11963.     assoc _ Association key: anObject value: maxVtx.
  11964.     objects addLast: assoc.
  11965.     anObject renderOn: self.
  11966.     (objects removeLast == assoc) ifFalse:[^self error:'Object stack is confused'].
  11967.     assoc value rasterPosZ > 2.0 ifFalse:[pickList add: assoc].! !
  11968.  
  11969. !B3DPickerEngine methodsFor: 'picking' stamp: 'ar 4/18/1999 00:08'!
  11970. topMostObject
  11971.     "Return the top most of all picked objects"
  11972.     ^pickList isEmpty
  11973.         ifTrue:[nil]
  11974.         ifFalse:[pickList first key]! !
  11975.  
  11976. !B3DPickerEngine methodsFor: 'picking' stamp: 'ar 6/2/1999 12:08'!
  11977. topMostVertex
  11978.     "Return the top most primitive vertex of all picked objects.
  11979.     Note: Except from the z value the vertex is *not* normalized yet 
  11980.         (e.g., there was no division by w)"
  11981.     ^pickList isEmpty
  11982.         ifTrue:[nil]
  11983.         ifFalse:[pickList first value]! !
  11984.  
  11985. !B3DPickerEngine methodsFor: 'private-rendering' stamp: 'ar 6/2/1999 11:54'!
  11986. primComputeMinIndexZ: primType vtxArray: vtxArray vtxSize: vtxSize idxArray: idxArray idxSize: idxSize
  11987.     "<primitive: 'b3dComputeMinIndexZ' module: 'Squeak3D'>"
  11988.     ^nil "Indicates failure"! !
  11989.  
  11990. !B3DPickerEngine methodsFor: 'private-rendering' stamp: 'ar 4/18/1999 03:01'!
  11991. primComputeMinZ: primType vtxArray: vtxArray vtxSize: vtxSize idxArray: idxArray idxSize: idxSize
  11992.     <primitive: 'b3dComputeMinZ' module: 'Squeak3D'>
  11993.     ^nil "Indicates failure"! !
  11994.  
  11995. !B3DPickerEngine methodsFor: 'private-rendering' stamp: 'ar 4/18/1999 02:26'!
  11996. privateTransformVB: vb
  11997.     "Transform the contents of the vertex buffer.
  11998.     Transforming may include normals (if lighting enabled) and textures (if textures enabled)."
  11999.     ^transformer processVertexBuffer: vb
  12000.                     modelView: transformer modelViewMatrix
  12001.                     projection: (transformer projectionMatrix composedWithGlobal: pickMatrix)! !
  12002.  
  12003. !B3DPickerEngine methodsFor: 'private-rendering' stamp: 'ar 6/4/1999 10:28'!
  12004. processIndexed: vb
  12005.     | idxArray vtxArray index vtx zValue minIndex minZ wValue |
  12006.     idxArray _ vb indexArray.
  12007.     vtxArray _ vb vertexArray.
  12008.     minZ _ 10.0.
  12009.     minIndex _ 0.
  12010.     1 to: vb indexCount do:[:i|
  12011.         index _ idxArray at: i.
  12012.         index = 0 ifFalse:[
  12013.             vtx _ vtxArray at: index.
  12014.             zValue _ vtx rasterPosZ.
  12015.             wValue _ vtx rasterPosW.
  12016.             wValue = 0.0 ifFalse:[zValue _ zValue / wValue].
  12017.             (minIndex = 0 or:[zValue < minZ]) ifTrue:[
  12018.                 minIndex _ index.
  12019.                 minZ _ zValue].
  12020.         ].
  12021.     ].
  12022.     ^minIndex! !
  12023.  
  12024. !B3DPickerEngine methodsFor: 'private-rendering' stamp: 'ar 4/18/1999 00:42'!
  12025. processIndexedLines: vb
  12026.     ^self processIndexed: vb! !
  12027.  
  12028. !B3DPickerEngine methodsFor: 'private-rendering' stamp: 'ar 4/18/1999 00:41'!
  12029. processIndexedQuads: vb
  12030.     ^self processIndexed: vb! !
  12031.  
  12032. !B3DPickerEngine methodsFor: 'private-rendering' stamp: 'ar 4/18/1999 00:41'!
  12033. processIndexedTriangles: vb
  12034.     ^self processIndexed: vb! !
  12035.  
  12036. !B3DPickerEngine methodsFor: 'private-rendering' stamp: 'ar 4/18/1999 00:43'!
  12037. processLineLoop: vb
  12038.     ^self processNonIndexed: vb! !
  12039.  
  12040. !B3DPickerEngine methodsFor: 'private-rendering' stamp: 'ar 4/18/1999 00:43'!
  12041. processLines: vb
  12042.     ^self processNonIndexed: vb! !
  12043.  
  12044. !B3DPickerEngine methodsFor: 'private-rendering' stamp: 'ar 6/2/1999 11:54'!
  12045. processNonIndexed: vb
  12046.     | vtxArray vtx zValue minZ minIndex wValue |
  12047.     vtxArray _ vb vertexArray.
  12048.     minZ _ 10.0.
  12049.     minIndex _ 0.
  12050.     1 to: vb vertexCount do:[:i|
  12051.         vtx _ vtxArray at: i.
  12052.         zValue _ vtx rasterPosZ.
  12053.         wValue _ vtx rasterPosW.
  12054.         wValue = 0.0 ifFalse:[zValue _ zValue / wValue].
  12055.         (minIndex = 0 or:[zValue < minZ]) ifTrue:[
  12056.             minIndex _ i.
  12057.             minZ _ zValue].
  12058.     ].
  12059.     ^minIndex! !
  12060.  
  12061. !B3DPickerEngine methodsFor: 'private-rendering' stamp: 'ar 4/18/1999 00:44'!
  12062. processPoints: vb
  12063.     ^self processNonIndexed: vb! !
  12064.  
  12065. !B3DPickerEngine methodsFor: 'private-rendering' stamp: 'ar 4/18/1999 00:43'!
  12066. processPolygon: vb
  12067.     ^self processNonIndexed: vb! !
  12068.  
  12069. !B3DPickerEngine methodsFor: 'private-rendering' stamp: 'ar 6/4/1999 10:28'!
  12070. processVertexBuffer: vb
  12071.     | minIndex minVertex minW |
  12072.     minIndex _ self primComputeMinIndexZ: vb primitive vtxArray: vb vertexArray vtxSize: vb vertexCount idxArray: vb indexArray idxSize: vb indexCount.
  12073.     minIndex == nil ifTrue:[minIndex _ super processVertexBuffer: vb].
  12074.     minIndex = 0 ifTrue:[^maxVtx].
  12075.     minVertex _ vb vertexArray at: minIndex.
  12076.     minW _ minVertex rasterPosW.
  12077.     minW = 0.0 ifFalse:[minVertex rasterPosZ: minVertex rasterPosZ / minW].
  12078.     ^minVertex! !
  12079.  
  12080. !B3DPickerEngine methodsFor: 'private-rendering' stamp: 'ar 11/7/1999 18:12'!
  12081. renderPrimitive
  12082.     "This is the main rendering loop for all operations"
  12083.     | visible minVertex |
  12084.     "Step 1: Check if the mesh is visible at all"
  12085.     visible _ self privateVisibleVB: vertexBuffer.
  12086.     visible == false ifTrue:[^nil].
  12087.  
  12088.     "Step 2: Transform vertices, normals, texture coords of the mesh"
  12089.     self privateTransformVB: vertexBuffer.
  12090.  
  12091.     "Step 3: Clip the mesh if necessary"
  12092.     visible _ self privateClipVB: vertexBuffer.
  12093.     visible == false ifTrue:[^nil].
  12094.  
  12095.     "Step 4: Collect the minimal/maximal distances for the current object."
  12096.     minVertex _ self processVertexBuffer: vertexBuffer.
  12097.     objects isEmpty ifFalse:[
  12098.         objects last value rasterPosZ > minVertex rasterPosZ 
  12099.             ifTrue:[objects last value: minVertex].
  12100.     ].
  12101.     ^nil! !
  12102.  
  12103. !B3DPickerPlugin methodsFor: 'primitives' stamp: 'ar 6/2/1999 11:59'!
  12104. b3dComputeMinIndexZ
  12105.     "Primitive. Compute and return the index for the minimal z value of all objects in the vertex buffer."
  12106.     | idxSize vtxSize primType vtxArray idxArray minIndex |
  12107.     self export: true.
  12108.     self inline: false.
  12109.     self var: #vtxArray declareC:'float *vtxArray'.
  12110.     self var: #idxArray declareC:'int *idxArray'.
  12111.     interpreterProxy methodArgumentCount = 5
  12112.         ifFalse:[^interpreterProxy primitiveFail].
  12113.     idxSize _ interpreterProxy stackIntegerValue: 0.
  12114.     vtxSize _ interpreterProxy stackIntegerValue: 2.
  12115.     primType _ interpreterProxy stackIntegerValue: 4.
  12116.     interpreterProxy failed ifTrue:[^nil].
  12117.     vtxArray _ self stackPrimitiveVertexArray: 3 ofSize: vtxSize.
  12118.     idxArray _ self stackPrimitiveIndexArray: 1 ofSize: idxSize validate: true forVertexSize: vtxSize.
  12119.     (vtxArray == nil or:[idxArray == nil or:[interpreterProxy failed]])
  12120.         ifTrue:[^interpreterProxy primitiveFail].
  12121.     (primType < 1 or:[primType > 6])
  12122.         ifTrue:[^interpreterProxy primitiveFail].
  12123.     primType <= 3 ifTrue:[
  12124.         minIndex _ self processNonIndexedIDX: vtxArray ofSize: vtxSize.
  12125.     ] ifFalse:[
  12126.         minIndex _ self processIndexedIDX: vtxArray ofSize: vtxSize idxArray: idxArray idxSize: idxSize.
  12127.     ].
  12128.     interpreterProxy failed ifFalse:[
  12129.         interpreterProxy pop: 6. "nArgs+rcvr"
  12130.         interpreterProxy pushInteger: minIndex.
  12131.     ].! !
  12132.  
  12133. !B3DPickerPlugin methodsFor: 'primitives' stamp: 'ar 4/18/1999 02:59'!
  12134. b3dComputeMinZ
  12135.     "Primitive. Compute and return the minimal z value of all objects in the vertex buffer."
  12136.     | idxSize vtxSize primType vtxArray idxArray minZ |
  12137.     self export: true.
  12138.     self inline: false.
  12139.     self var: #vtxArray declareC:'float *vtxArray'.
  12140.     self var: #idxArray declareC:'int *idxArray'.
  12141.     self var: #minZ declareC:'double minZ'.
  12142.     interpreterProxy methodArgumentCount = 5
  12143.         ifFalse:[^interpreterProxy primitiveFail].
  12144.     idxSize _ interpreterProxy stackIntegerValue: 0.
  12145.     vtxSize _ interpreterProxy stackIntegerValue: 2.
  12146.     primType _ interpreterProxy stackIntegerValue: 4.
  12147.     interpreterProxy failed ifTrue:[^nil].
  12148.     vtxArray _ self stackPrimitiveVertexArray: 3 ofSize: vtxSize.
  12149.     idxArray _ self stackPrimitiveIndexArray: 1 ofSize: idxSize validate: true forVertexSize: vtxSize.
  12150.     (vtxArray == nil or:[idxArray == nil or:[interpreterProxy failed]])
  12151.         ifTrue:[^interpreterProxy primitiveFail].
  12152.     (primType < 1 or:[primType > 6])
  12153.         ifTrue:[^interpreterProxy primitiveFail].
  12154.     primType <= 3 ifTrue:[
  12155.         minZ _ self processNonIndexed: vtxArray ofSize: vtxSize.
  12156.     ] ifFalse:[
  12157.         minZ _ self processIndexed: vtxArray ofSize: vtxSize idxArray: idxArray idxSize: idxSize.
  12158.     ].
  12159.     interpreterProxy failed ifFalse:[
  12160.         interpreterProxy pop: 6. "nArgs+rcvr"
  12161.         interpreterProxy pushFloat: minZ.
  12162.     ].! !
  12163.  
  12164. !B3DPickerPlugin methodsFor: 'processing' stamp: 'ar 4/18/1999 03:05'!
  12165. processIndexed: vtxArray ofSize: vtxSize idxArray: idxArray idxSize: idxSize
  12166.     | vtxPtr zValue wValue minZ index |
  12167.     self returnTypeC:'double'.
  12168.     self var: #vtxArray declareC:'float *vtxArray'.
  12169.     self var: #vtxPtr declareC:'float *vtxPtr'.
  12170.     self var: #idxArray declareC:'int *idxArray'.
  12171.     self var: #wValue declareC:'double wValue'.
  12172.     self var: #zValue declareC:'double zValue'.
  12173.     self var: #minZ declareC:'double minZ'.
  12174.     minZ _ 10.0.
  12175.     1 to: idxSize do:[:i|
  12176.         index _ idxArray at: i.
  12177.         index > 0 ifTrue:[
  12178.             vtxPtr _ vtxArray + (index-1 * PrimVertexSize).
  12179.             zValue _ vtxPtr at: PrimVtxRasterPosZ.
  12180.             wValue _ vtxPtr at: PrimVtxRasterPosW.
  12181.             wValue = 0.0 ifFalse:[zValue _ zValue / wValue].
  12182.             zValue < minZ ifTrue:[minZ _ zValue].
  12183.         ].
  12184.     ].
  12185.     ^minZ! !
  12186.  
  12187. !B3DPickerPlugin methodsFor: 'processing' stamp: 'ar 6/2/1999 12:00'!
  12188. processIndexedIDX: vtxArray ofSize: vtxSize idxArray: idxArray idxSize: idxSize
  12189.     | vtxPtr zValue wValue minZ minIndex index |
  12190.     self var: #vtxArray declareC:'float *vtxArray'.
  12191.     self var: #vtxPtr declareC:'float *vtxPtr'.
  12192.     self var: #idxArray declareC:'int *idxArray'.
  12193.     self var: #wValue declareC:'double wValue'.
  12194.     self var: #zValue declareC:'double zValue'.
  12195.     self var: #minZ declareC:'double minZ'.
  12196.     minZ _ 10.0.
  12197.     minIndex _ 0.
  12198.     1 to: idxSize do:[:i|
  12199.         index _ idxArray at: i.
  12200.         index > 0 ifTrue:[
  12201.             vtxPtr _ vtxArray + (index-1 * PrimVertexSize).
  12202.             zValue _ vtxPtr at: PrimVtxRasterPosZ.
  12203.             wValue _ vtxPtr at: PrimVtxRasterPosW.
  12204.             wValue = 0.0 ifFalse:[zValue _ zValue / wValue].
  12205.             (minIndex = 0 or:[zValue < minZ]) ifTrue:[
  12206.                 minIndex _ i.
  12207.                 minZ _ zValue].
  12208.         ].
  12209.     ].
  12210.     ^minIndex! !
  12211.  
  12212. !B3DPickerPlugin methodsFor: 'processing' stamp: 'ar 4/18/1999 02:49'!
  12213. processNonIndexed: vtxArray ofSize: vtxSize
  12214.     | vtxPtr zValue wValue minZ |
  12215.     self returnTypeC:'double'.
  12216.     self var: #vtxArray declareC:'float *vtxArray'.
  12217.     self var: #vtxPtr declareC:'float *vtxPtr'.
  12218.     self var: #wValue declareC:'double wValue'.
  12219.     self var: #zValue declareC:'double zValue'.
  12220.     self var: #minZ declareC:'double minZ'.
  12221.     minZ _ 10.0.
  12222.     vtxPtr _ vtxArray.
  12223.     1 to: vtxSize do:[:i|
  12224.         zValue _ vtxPtr at: PrimVtxRasterPosZ.
  12225.         wValue _ vtxPtr at: PrimVtxRasterPosW.
  12226.         wValue = 0.0 ifFalse:[zValue _ zValue / wValue].
  12227.         zValue < minZ ifTrue:[minZ _ zValue].
  12228.     ].
  12229.     ^minZ! !
  12230.  
  12231. !B3DPickerPlugin methodsFor: 'processing' stamp: 'ar 6/2/1999 12:00'!
  12232. processNonIndexedIDX: vtxArray ofSize: vtxSize
  12233.     | vtxPtr zValue wValue minZ minIndex |
  12234.     self var: #vtxArray declareC:'float *vtxArray'.
  12235.     self var: #vtxPtr declareC:'float *vtxPtr'.
  12236.     self var: #wValue declareC:'double wValue'.
  12237.     self var: #zValue declareC:'double zValue'.
  12238.     self var: #minZ declareC:'double minZ'.
  12239.     minZ _ 10.0.
  12240.     minIndex _ 0.
  12241.     vtxPtr _ vtxArray.
  12242.     1 to: vtxSize do:[:i|
  12243.         zValue _ vtxPtr at: PrimVtxRasterPosZ.
  12244.         wValue _ vtxPtr at: PrimVtxRasterPosW.
  12245.         wValue = 0.0 ifFalse:[zValue _ zValue / wValue].
  12246.         (minIndex = 0 or:[zValue < minZ]) ifTrue:[
  12247.             minIndex _ i.
  12248.             minZ _ zValue].
  12249.     ].
  12250.     ^minIndex! !
  12251.  
  12252. This class is used to define the pool dictionary B3DConstants.!
  12253. !B3DPoolDefiner class methodsFor: 'class initialization' stamp: 'ar 2/8/1999 17:21'!
  12254. initialize
  12255.     "B3DPoolDefiner initialize"
  12256.     self initPool.! !
  12257.  
  12258. !B3DPoolDefiner class methodsFor: 'pool definition' stamp: 'ar 2/13/1999 20:30'!
  12259. defineClipConstants: dict
  12260.     "Initialize the clipper constants"
  12261.     "B3DPoolDefiner initPool"
  12262.     self initFromSpecArray:
  12263.     #(
  12264.         (InLeftBit        16r001)
  12265.         (OutLeftBit        16r002)
  12266.         (InRightBit        16r004)
  12267.         (OutRightBit        16r008)
  12268.         (InTopBit        16r010)
  12269.         (OutTopBit        16r020)
  12270.         (InBottomBit        16r040)
  12271.         (OutBottomBit    16r080)
  12272.         (InFrontBit        16r100)
  12273.         (OutFrontBit        16r200)
  12274.         (InBackBit        16r400)
  12275.         (OutBackBit        16r800)
  12276.  
  12277.         (InAllMask        16r555)
  12278.         (OutAllMask        16rAAA)
  12279.     ) in: dict.! !
  12280.  
  12281. !B3DPoolDefiner class methodsFor: 'pool definition' stamp: 'ar 2/16/1999 01:22'!
  12282. defineMaterialAndLights: dict
  12283.     "Initialize constants used for materials and lights"
  12284.     "B3DPoolDefiner initPool"
  12285.     self initFromSpecArray:
  12286.     #(
  12287.         "MaterialColor stuff"
  12288.         (AmbientPart 0)
  12289.         (AmbientRed 0)
  12290.         (AmbientGreen 1)
  12291.         (AmbientBlue 2)
  12292.         (AmbientAlpha 3)
  12293.  
  12294.         (DiffusePart 4)
  12295.         (DiffuseRed 4)
  12296.         (DiffuseGreen 5)
  12297.         (DiffuseBlue 6)
  12298.         (DiffuseAlpha 7)
  12299.  
  12300.         (SpecularPart 8)    
  12301.         (SpecularRed 8)
  12302.         (SpecularGreen 9)
  12303.         (SpecularBlue 10)
  12304.         (SpecularAlpha 11)
  12305.  
  12306.         (MaterialColorSize 12)    "Size of B3DMaterialColor"
  12307.  
  12308.         "Material definition"
  12309.         (EmissionPart 12)
  12310.         (EmissionRed 12)
  12311.         (EmissionGreen 13)
  12312.         (EmissionBlue 14)
  12313.         (EmissionAlpha 15)
  12314.  
  12315.         (MaterialShininess 16)
  12316.  
  12317.         (MaterialSize 17)            "Size of B3DMaterial"
  12318.  
  12319.         "PrimitiveLight definition"
  12320.         (PrimLightPosition 12)
  12321.         (PrimLightPositionX 12)
  12322.         (PrimLightPositionY 13)
  12323.         (PrimLightPositionZ 14)
  12324.  
  12325.         (PrimLightDirection 15)
  12326.         (PrimLightDirectionX 15)
  12327.         (PrimLightDirectionY 16)
  12328.         (PrimLightDirectionZ 17)
  12329.  
  12330.         (PrimLightAttenuation 17)
  12331.         (PrimLightAttenuationConstant 17)
  12332.         (PrimLightAttenuationLinear 18)
  12333.         (PrimLightAttenuationSquared 19)
  12334.  
  12335.         (PrimLightFlags 20)
  12336.         "Spot light stuff"
  12337.         (SpotLightMinCos 21)
  12338.         (SpotLightMaxCos 22)
  12339.         (SpotLightDeltaCos 23)
  12340.         (SpotLightExponent 24)
  12341.  
  12342.         (PrimLightSize 32)        "Round up to power of 2"
  12343.  
  12344.         "Primitive light flags"
  12345.         (FlagPositional 16r0001)    "Light has an associated position"
  12346.         (FlagDirectional 16r0002)    "Light has an associated direction"
  12347.         (FlagAttenuated 16r0004)    "Light is attenuated"
  12348.         (FlagHasSpot 16r0008)    "Spot values are valid"
  12349.         (FlagAmbientPart 16r0100)    "Light has ambient part"
  12350.         (FlagDiffusePart 16r0200)    "Light has diffuse part"
  12351.         (FlagSpecularPart 16r0400)    "Light has specular part"
  12352.  
  12353.     ) in: dict.! !
  12354.  
  12355. !B3DPoolDefiner class methodsFor: 'pool definition' stamp: 'ar 2/8/1999 20:15'!
  12356. defineMatrixFlags: dict
  12357.     "Define the flags for analyzing vertices"
  12358.     "B3DPoolDefiner initPool"
  12359.     self initFromSpecArray:
  12360.     #(
  12361.         (FlagM44Identity 1)        "Matrix is identity"
  12362.         (FlagM44NoPerspective 2) "Matrix has no perspective part"
  12363.         (FlagM44NoTranslation 4) "Matrix has no translation"
  12364.     ) in: dict! !
  12365.  
  12366. !B3DPoolDefiner class methodsFor: 'pool definition' stamp: 'ar 2/13/1999 23:41'!
  12367. definePrimitiveTypes: dict
  12368.     "Initialize the types of Primitives"
  12369.     "B3DPoolDefiner initPool"
  12370.     self initFromSpecArray:
  12371.     #(
  12372.         (PrimTypePoints 1)
  12373.         (PrimTypeLines 2)
  12374.         (PrimTypePolygon 3)
  12375.         (PrimTypeIndexedLines 4)
  12376.         (PrimTypeIndexedTriangles 5)
  12377.         (PrimTypeIndexedQuads 6)
  12378.         (PrimTypeMax 6)    "Max used primitive type"
  12379.     ) in: dict.! !
  12380.  
  12381. !B3DPoolDefiner class methodsFor: 'pool definition' stamp: 'ar 4/4/1999 00:46'!
  12382. definePrimitiveVertexIndexes: dict
  12383.     "Define the indexes for primitive vertices"
  12384.     "B3DPoolDefiner initPool"
  12385.     self initFromSpecArray:
  12386.     #(
  12387.         "Full vertex size is 16 to simplify index computation"
  12388.         (PrimVertexSize 16)
  12389.  
  12390.         "Position"
  12391.         (PrimVtxPosition 0)
  12392.         (PrimVtxPositionX 0)
  12393.         (PrimVtxPositionY 1)
  12394.         (PrimVtxPositionZ 2)
  12395.  
  12396.         "Normal"
  12397.         (PrimVtxNormal 3)
  12398.         (PrimVtxNormalX 3)
  12399.         (PrimVtxNormalY 4)
  12400.         (PrimVtxNormalZ 5)
  12401.  
  12402.         "Tex coord"
  12403.         (PrimVtxTexCoords 6)
  12404.         (PrimVtxTexCoordU 6)
  12405.         (PrimVtxTexCoordV 7)
  12406.  
  12407.         "RasterPos"
  12408.         (PrimVtxRasterPos 8)
  12409.         (PrimVtxRasterPosX 8)
  12410.         (PrimVtxRasterPosY 9)
  12411.         (PrimVtxRasterPosZ 10)
  12412.         (PrimVtxRasterPosW 11)
  12413.  
  12414.         "Color"
  12415.         (PrimVtxColor32 12)
  12416.         "Clip flags"
  12417.         (PrimVtxClipFlags 13)
  12418.  
  12419.         "(Integer) window position"
  12420.         (PrimVtxWindowPosX 14)
  12421.         (PrimVtxWindowPosY 15)
  12422.     ) in: dict! !
  12423.  
  12424. !B3DPoolDefiner class methodsFor: 'pool definition' stamp: 'ar 2/8/1999 17:34'!
  12425. defineVBConstants: dict
  12426.     "Initialize the vertex buffer constants"
  12427.     "B3DPoolDefiner initPool"
  12428.     self initFromSpecArray:
  12429.     #(
  12430.         "Vertex color tracking flags. These tracks define what part of 
  12431.         the material in the shader is determined by the vertex color (if given)."
  12432.         (VBTrackAmbient 1)        "ambient part"
  12433.         (VBTrackDiffuse 2)        "diffuse part"
  12434.         (VBTrackSpecular 4)        "specular part"
  12435.         (VBTrackEmission 8)        "emission part -- i.e. simply add vertex color to output"
  12436.         (VBNoTrackMask 4294967280) "Mask out the above flags"
  12437.  
  12438.         "Vertex attribute flags. These flags determine if the primitive
  12439.         vertices include these attributes. Note that color is not included
  12440.         below - it is fully specified by the color tracking flags above."
  12441.         (VBVtxHasNormals 16)    "per vertex normals included"
  12442.         (VBVtxHasTexCoords 32)    "per vertex tex coords inclueded"
  12443.  
  12444.         "Shader flags stored in the vertex buffer"
  12445.         (VBTwoSidedLighting 64)    "Do we shade front and back faces differently?!!"
  12446.         (VBUseLocalViewer 128)    "Do we use a local viewer model for specular colors?!!"
  12447.     ) in: dict.! !
  12448.  
  12449. !B3DPoolDefiner class methodsFor: 'pool definition' stamp: 'ar 2/8/1999 17:20'!
  12450. initFromSpecArray: specArray in: aDictionary
  12451.     specArray do:[:spec|
  12452.         self initPoolVariable: spec first value: spec last in: aDictionary.
  12453.     ]! !
  12454.  
  12455. !B3DPoolDefiner class methodsFor: 'pool definition' stamp: 'ar 2/8/1999 17:23'!
  12456. initPool
  12457.     "B3DPoolDefiner initPool"
  12458.     | poolName |
  12459.     poolName _ self poolName asSymbol.
  12460.     (Smalltalk includesKey: poolName) ifFalse:[
  12461.         Smalltalk declare: poolName from: Undeclared.
  12462.     ].
  12463.     (Smalltalk at: poolName) isNil ifTrue:[
  12464.         (Smalltalk associationAt: poolName) value: Dictionary new.
  12465.     ].
  12466.     self initPool: (Smalltalk at: poolName).! !
  12467.  
  12468. !B3DPoolDefiner class methodsFor: 'pool definition' stamp: 'ar 2/15/1999 04:14'!
  12469. initPool: aDictionary
  12470.     "B3DPoolDefiner initPool"
  12471.     self defineVBConstants: aDictionary.
  12472.     self definePrimitiveVertexIndexes: aDictionary.
  12473.     self defineMatrixFlags: aDictionary.
  12474.     self defineClipConstants: aDictionary.
  12475.     self definePrimitiveTypes: aDictionary.
  12476.     self defineMaterialAndLights: aDictionary.! !
  12477.  
  12478. !B3DPoolDefiner class methodsFor: 'pool definition' stamp: 'ar 2/8/1999 17:23'!
  12479. initPoolFull    "B3DPoolDefiner initPoolFull"
  12480.     "Move old stuff to Undeclared and re-initialize the receiver"
  12481.     | pool |
  12482.     pool _ Smalltalk at: self poolName asSymbol ifAbsent:[Dictionary new].
  12483.     pool associationsDo:[:assoc|
  12484.         Undeclared declare: assoc key from: pool.
  12485.     ].
  12486.     self initPool.
  12487.     Undeclared removeUnreferencedKeys.! !
  12488.  
  12489. !B3DPoolDefiner class methodsFor: 'pool definition' stamp: 'ar 2/8/1999 17:20'!
  12490. initPoolVariable: token value: value in: aDictionary
  12491.     aDictionary declare: token from: Undeclared.
  12492.     (aDictionary associationAt: token) value: value.! !
  12493.  
  12494. !B3DPoolDefiner class methodsFor: 'pool definition' stamp: 'ar 2/8/1999 17:22'!
  12495. poolName
  12496.     ^#B3DEngineConstants! !
  12497.  
  12498. !B3DPositionalLight methodsFor: 'initialize' stamp: 'ar 2/7/1999 19:14'!
  12499. from3DS: aDictionary
  12500.     "Initialize the receiver from a 3DS point light"
  12501.     | color |
  12502.     position _ aDictionary at: #position.
  12503.     color _ aDictionary at: #color.
  12504.     lightColor _ B3DMaterialColor color: color.
  12505.     attenuation _ B3DLightAttenuation constant: 1.0 linear: 0.0 squared: 0.0.! !
  12506.  
  12507. !B3DPositionalLight methodsFor: 'accessing' stamp: 'ar 2/7/1999 19:05'!
  12508. attenuation
  12509.     ^attenuation! !
  12510.  
  12511. !B3DPositionalLight methodsFor: 'accessing' stamp: 'ar 2/7/1999 19:05'!
  12512. attenuation: aLightAttenuation
  12513.     attenuation _ aLightAttenuation! !
  12514.  
  12515. !B3DPositionalLight methodsFor: 'accessing' stamp: 'ar 2/7/1999 19:04'!
  12516. position
  12517.     ^position! !
  12518.  
  12519. !B3DPositionalLight methodsFor: 'accessing' stamp: 'ar 2/7/1999 19:04'!
  12520. position: aVector
  12521.     position _ aVector! !
  12522.  
  12523. !B3DPositionalLight methodsFor: 'shading' stamp: 'ar 2/7/1999 16:54'!
  12524. computeAttenuationFor: distance
  12525.     "Compute the attenuation for the given distance"
  12526.     ^attenuation computeAttenuationFor: distance! !
  12527.  
  12528. !B3DPositionalLight methodsFor: 'shading' stamp: 'ar 2/8/1999 02:01'!
  12529. computeDirectionTo: aB3DPrimitiveVertex
  12530.     "Compute the lights direction to the given vertex"
  12531.     ^aB3DPrimitiveVertex position - position! !
  12532.  
  12533. !B3DPositionalLight methodsFor: 'converting' stamp: 'ar 2/15/1999 21:58'!
  12534. asPrimitiveLight
  12535.     "Convert the receiver into a B3DPrimitiveLight"
  12536.     | primLight flags |
  12537.     primLight _ B3DPrimitiveLight new.
  12538.     primLight position: position.
  12539.     flags _ FlagPositional.
  12540.     self attenuation isIdentity not ifTrue:[
  12541.         primLight attenuation: self attenuation.
  12542.         flags _ flags bitOr: FlagAttenuated].
  12543.     lightColor ambientPart isZero ifFalse:[
  12544.         primLight ambientPart: lightColor ambientPart.
  12545.         flags _ flags bitOr: FlagAmbientPart].
  12546.     lightColor diffusePart isZero ifFalse:[
  12547.         primLight diffusePart: lightColor diffusePart.
  12548.         flags _ flags bitOr: FlagDiffusePart].
  12549.     lightColor specularPart isZero ifFalse:[
  12550.         primLight specularPart: lightColor specularPart.
  12551.         flags _ flags bitOr: FlagSpecularPart].
  12552.     primLight flags: flags.
  12553.     ^primLight! !
  12554.  
  12555. !B3DPositionalLight methodsFor: 'converting' stamp: 'ar 2/8/1999 01:29'!
  12556. transformedBy: aTransformer
  12557.     ^(super transformedBy: aTransformer) position: (aTransformer transformPosition: position)! !
  12558.  
  12559. !B3DPositionalLight class methodsFor: 'instance creation' stamp: 'ar 2/6/1999 23:42'!
  12560. from3DS: aDictionary
  12561.     ^self new from3DS: aDictionary! !
  12562.  
  12563. !B3DPrimitiveClipper methodsFor: 'clip flags' stamp: 'ar 4/18/1999 02:05'!
  12564. determineClipFlags: vtxArray count: vtxCount
  12565.     <primitive: 'b3dDetermineClipFlags' module:'Squeak3D'>
  12566.     ^super determineClipFlags: vtxArray count: vtxCount! !
  12567.  
  12568. !B3DPrimitiveClipper methodsFor: 'clipping polygons' stamp: 'ar 4/18/1999 02:08'!
  12569. clipPolygon: vtxArray count: vtxCount with: tempVtxArray mask: outMask
  12570.     <primitive:'b3dClipPolygon' module:'Squeak3D'>
  12571.     ^super clipPolygon: vtxArray count: vtxCount with: tempVtxArray mask: outMask! !
  12572.  
  12573. !B3DPrimitiveClipper methodsFor: 'private' stamp: 'ar 4/18/1999 02:07'!
  12574. primNextClippedTriangleAfter: firstIndex vertices: vtxArray count: vtxCount indexes: idxArray count: idxCount
  12575.     <primitive: 'b3dPrimitiveNextClippedTriangle' module:'Squeak3D'>
  12576.     ^super primNextClippedTriangleAfter: firstIndex vertices: vtxArray count: vtxCount indexes: idxArray count: idxCount! !
  12577.  
  12578. !B3DPrimitiveEdge methodsFor: 'initialize' stamp: 'ar 4/3/1999 04:25'!
  12579. from: vtx0 to: vtx1
  12580.     (vtx0 sortsBefore: vtx1) 
  12581.         ifTrue:[v0 _ vtx0. v1 _ vtx1]
  12582.         ifFalse:[v1 _ vtx0. v0 _ vtx1].! !
  12583.  
  12584. !B3DPrimitiveEdge methodsFor: 'initialize' stamp: 'ar 4/18/1999 08:05'!
  12585. initializePass1
  12586.     "Assume: v0 sortsBefore: v1"
  12587.     xValue _ v0 windowPosX.
  12588.     yValue _ v0 windowPosY.
  12589.     zValue _ v0 rasterPosZ.
  12590.     xIncrement _ (v1 windowPosX - v0 windowPosX) // nLines.
  12591.     zIncrement _ (v1 rasterPosZ - v0 rasterPosZ) / nLines.! !
  12592.  
  12593. !B3DPrimitiveEdge methodsFor: 'initialize' stamp: 'ar 4/4/1999 21:34'!
  12594. v0: vtx0 v1: vtx1
  12595.     v0 _ vtx0.
  12596.     v1 _ vtx1.
  12597.     flags _ 0.
  12598.     nLines _ (vtx1 windowPosY bitShift: -12) - (vtx0 windowPosY bitShift: -12).! !
  12599.  
  12600. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/4/1999 02:41'!
  12601. flags
  12602.     ^flags! !
  12603.  
  12604. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/4/1999 02:41'!
  12605. flags: aNumber
  12606.     flags _ aNumber! !
  12607.  
  12608. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:33'!
  12609. leftFace
  12610.     ^leftFace! !
  12611.  
  12612. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:33'!
  12613. leftFace: aFace
  12614.     leftFace _ aFace! !
  12615.  
  12616. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/3/1999 03:25'!
  12617. nLines
  12618.     ^nLines! !
  12619.  
  12620. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/3/1999 03:25'!
  12621. nLines: aNumber
  12622.     nLines _ aNumber! !
  12623.  
  12624. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:33'!
  12625. rightFace
  12626.     ^rightFace! !
  12627.  
  12628. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:33'!
  12629. rightFace: aFace
  12630.     rightFace _ aFace.! !
  12631.  
  12632. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/4/1999 20:58'!
  12633. vertex0
  12634.     ^v0! !
  12635.  
  12636. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/4/1999 20:58'!
  12637. vertex1
  12638.     ^v1! !
  12639.  
  12640. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/6/1999 23:21'!
  12641. xIncrement    
  12642.     ^xIncrement! !
  12643.  
  12644. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:48'!
  12645. xValue
  12646.     ^xValue! !
  12647.  
  12648. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/5/1999 22:25'!
  12649. xValue: aNumber
  12650.     xValue _ aNumber! !
  12651.  
  12652. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:48'!
  12653. yValue
  12654.     ^yValue! !
  12655.  
  12656. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:48'!
  12657. zValue
  12658.     ^zValue! !
  12659.  
  12660. !B3DPrimitiveEdge methodsFor: 'accessing' stamp: 'ar 4/6/1999 01:23'!
  12661. zValue: aNumber
  12662.     zValue _ aNumber! !
  12663.  
  12664. !B3DPrimitiveEdge methodsFor: 'processing' stamp: 'ar 4/5/1999 02:45'!
  12665. stepToNextLine
  12666.     "Step to the next scan line"
  12667.     xValue _ xValue + xIncrement.
  12668.     yValue _ yValue + 4096.
  12669.     zValue _ zValue + zIncrement.! !
  12670.  
  12671. !B3DPrimitiveEdge methodsFor: 'printing' stamp: 'ar 4/4/1999 23:35'!
  12672. printOn: aStream
  12673.     super printOn: aStream.
  12674.     aStream
  12675.         nextPut:$(;
  12676.         print: (v0 windowPos bitShiftPoint:-12);
  12677.         nextPutAll:' - ';
  12678.         print: (v1 windowPos bitShiftPoint: -12);
  12679.         nextPutAll:' nLines = ';
  12680.         print: nLines;
  12681.         nextPut:$).! !
  12682.  
  12683. !B3DPrimitiveEdgeList methodsFor: 'initialize' stamp: 'ar 4/4/1999 01:38'!
  12684. initialize
  12685.     array _ Array new: 100.
  12686.     tally _ 0.! !
  12687.  
  12688. !B3DPrimitiveEdgeList methodsFor: 'initialize' stamp: 'ar 4/4/1999 21:20'!
  12689. reset
  12690.     1 to: tally do:[:i| array at: i put: nil].
  12691.     tally _ 0.! !
  12692.  
  12693. !B3DPrimitiveEdgeList methodsFor: 'accessing' stamp: 'ar 4/4/1999 21:42'!
  12694. at: index
  12695.     ^array at: index! !
  12696.  
  12697. !B3DPrimitiveEdgeList methodsFor: 'accessing' stamp: 'ar 4/4/1999 21:01'!
  12698. first
  12699.     ^array at: 1! !
  12700.  
  12701. !B3DPrimitiveEdgeList methodsFor: 'accessing' stamp: 'ar 4/4/1999 21:42'!
  12702. size
  12703.     ^tally! !
  12704.  
  12705. !B3DPrimitiveEdgeList methodsFor: 'accessing' stamp: 'ar 4/6/1999 03:58'!
  12706. xValues
  12707.     ^(array copyFrom: 1 to: tally) collect:[:e| e xValue]! !
  12708.  
  12709. !B3DPrimitiveEdgeList methodsFor: 'adding' stamp: 'ar 4/4/1999 23:44'!
  12710. add: edge1 and: edge2 beforeIndex: index
  12711.     tally+1 >= array size ifTrue:[self grow].
  12712.     tally+2 to: index+2 by: -1 do:[:i|array at: i put: (array at:i-2)].
  12713.     "array replaceFrom: index+2 to: tally+2 with: array startingAt: index."
  12714.     array at: index put: edge1.
  12715.     array at: index+1 put: edge2.
  12716.     tally _ tally + 2.! !
  12717.  
  12718. !B3DPrimitiveEdgeList methodsFor: 'adding' stamp: 'ar 4/4/1999 23:45'!
  12719. add: edge beforeIndex: index
  12720.     tally = array size ifTrue:[self grow].
  12721.     tally+1 to: index+1 by: -1 do:[:i|array at: i put: (array at:i-1)].
  12722.     "array replaceFrom: index+1 to: tally+1 with: array startingAt: index."
  12723.     array at: index put: edge.
  12724.     tally _ tally + 1! !
  12725.  
  12726. !B3DPrimitiveEdgeList methodsFor: 'enumerating' stamp: 'ar 4/5/1999 02:27'!
  12727. do: aBlock
  12728.     1 to: tally do:[:i| aBlock value: (array at: i)].! !
  12729.  
  12730. !B3DPrimitiveEdgeList methodsFor: 'enumerating' stamp: 'ar 4/4/1999 01:39'!
  12731. xValue: xValue from: firstIndex do: aBlock
  12732.     "Enumerate the entries in the insertion list starting at the given first index.
  12733.     Evaluate aBlock with the entries having the requested x value. Return the index
  12734.     after the last element touched."
  12735.     | edge |
  12736.     firstIndex to: tally do:[:i|
  12737.         edge _ array at: i.
  12738.         edge xValue = xValue ifFalse:[^i].
  12739.         aBlock value: edge.
  12740.     ].
  12741.     ^tally+1! !
  12742.  
  12743. !B3DPrimitiveEdgeList methodsFor: 'testing' stamp: 'ar 4/4/1999 23:09'!
  12744. isEmpty
  12745.     ^tally = 0! !
  12746.  
  12747. !B3DPrimitiveEdgeList methodsFor: 'sorting' stamp: 'ar 4/5/1999 01:41'!
  12748. firstIndexForInserting: xValue
  12749.     "Return the first possible index for inserting an object with the given xValue"
  12750.     | index |
  12751.     index _ self indexForInserting: xValue.
  12752.     [index > 1 and:[(array at: index-1) xValue = xValue]]
  12753.         whileTrue:[index _ index-1].
  12754.     ^index! !
  12755.  
  12756. !B3DPrimitiveEdgeList methodsFor: 'sorting' stamp: 'ar 4/5/1999 01:41'!
  12757. indexForInserting: xValue
  12758.     "Return the appropriate index for inserting the given x value"
  12759.     | index low high |
  12760.     low _ 1.
  12761.     high _ tally.
  12762.     [index _ high + low // 2.
  12763.     low > high]
  12764.         whileFalse:[
  12765.             (array at: index) xValue <= xValue
  12766.                 ifTrue: [low _ index + 1]
  12767.                 ifFalse: [high _ index - 1]].
  12768.     ^low! !
  12769.  
  12770. !B3DPrimitiveEdgeList methodsFor: 'private' stamp: 'ar 4/4/1999 01:38'!
  12771. grow
  12772.     | newArray |
  12773.     newArray _ array species new: array size + 100.
  12774.     newArray replaceFrom: 1 to: array size with: array startingAt: 1.
  12775.     array _ newArray.! !
  12776.  
  12777. !B3DPrimitiveEdgeList class methodsFor: 'instance creation' stamp: 'ar 4/4/1999 04:27'!
  12778. new
  12779.     ^super new initialize! !
  12780.  
  12781. I am a basic render engine with some primitive level support for transformation, lighting and (once it is done) clipping.!
  12782. !B3DPrimitiveEngine class methodsFor: 'accessing' stamp: 'ar 4/16/1999 06:45'!
  12783. clipper
  12784.     ^B3DPrimitiveClipper
  12785.     "^B3DVertexClipper"! !
  12786.  
  12787. !B3DPrimitiveEngine class methodsFor: 'accessing' stamp: 'ar 4/12/1999 03:47'!
  12788. rasterizer
  12789.     "Return the rasterizer to use with this engine"
  12790.     ^B3DPrimitiveRasterizer! !
  12791.  
  12792. !B3DPrimitiveEngine class methodsFor: 'accessing' stamp: 'ar 2/17/1999 04:24'!
  12793. shader
  12794.     "Return the shader to use with this engine"
  12795.     ^B3DPrimitiveShader! !
  12796.  
  12797. !B3DPrimitiveEngine class methodsFor: 'accessing' stamp: 'ar 2/17/1999 04:24'!
  12798. transformer
  12799.     "Return the transformer to use with this engine"
  12800.     ^B3DPrimitiveTransformer! !
  12801.  
  12802. !B3DPrimitiveFace methodsFor: 'initialize' stamp: 'ar 4/5/1999 18:29'!
  12803. initializeDepthBounds
  12804.     "Compute minZ/maxZ"
  12805.     v0 rasterPosZ <= v1 rasterPosZ ifTrue:[
  12806.         v1 rasterPosZ <= v2 rasterPosZ
  12807.             ifTrue:[minZ _ v0 rasterPosZ. maxZ _ v2 rasterPosZ]
  12808.             ifFalse:[v0 rasterPosZ <= v2 rasterPosZ
  12809.                         ifTrue:[minZ _ v0 rasterPosZ. maxZ _ v1 rasterPosZ]
  12810.                         ifFalse:[minZ _ v2 rasterPosZ. maxZ _ v1 rasterPosZ]].
  12811.     ] ifFalse:[
  12812.         v2 rasterPosZ <= v1 rasterPosZ
  12813.             ifTrue:[minZ _ v2 rasterPosZ. maxZ _ v0 rasterPosZ]
  12814.             ifFalse:[v0 rasterPosZ <= v2 rasterPosZ
  12815.                         ifTrue:[minZ _ v1 rasterPosZ. maxZ _ v2 rasterPosZ]
  12816.                         ifFalse:[minZ _ v1 rasterPosZ. maxZ _ v0 rasterPosZ]].
  12817.     ].
  12818. ! !
  12819.  
  12820. !B3DPrimitiveFace methodsFor: 'initialize' stamp: 'ar 4/8/1999 04:32'!
  12821. initializePass1
  12822.     "Assume: v0 sortsBefore: v1 sortsBefore: v2"
  12823.     | area majorDz minorDz |
  12824.     self initializeDepthBounds. "Compute minZ/maxZ"
  12825.     "Compute the major and minor reference edges"
  12826.     majorDx _ v2 rasterPosX - v0 rasterPosX.
  12827.     majorDy _ v2 rasterPosY - v0 rasterPosY.
  12828.     minorDx _ v1 rasterPosX - v0 rasterPosX.
  12829.     minorDy _ v1 rasterPosY - v0 rasterPosY.
  12830.  
  12831.     "Compute the inverse area of the face"
  12832.     area _ (majorDx * minorDy) - (minorDx * majorDy).
  12833.     ((area > -0.001) and:[area < 0.001])
  12834.         ifTrue:[oneOverArea _ 0.0]
  12835.         ifFalse:[oneOverArea _ 1.0 / area].
  12836.     "Compute dzdx and dzdy"
  12837.     majorDz _ v2 rasterPosZ - v0 rasterPosZ.
  12838.     minorDz _ v1 rasterPosZ - v0 rasterPosZ.
  12839.     dzdx _ oneOverArea * ((majorDz * minorDy) - (minorDz * majorDy)).
  12840.     dzdy _ oneOverArea * ((majorDx * minorDz) - (majorDz * minorDx)).
  12841. ! !
  12842.  
  12843. !B3DPrimitiveFace methodsFor: 'initialize' stamp: 'ar 4/18/1999 06:35'!
  12844. initializePass2
  12845.     "The receiver is about to be drawn.
  12846.     Initialize all the attributes deferred until now."
  12847.     | majorDv minorDv dvdx dvdy w0 w1 w2 baseValue rAttr gAttr bAttr aAttr wAttr sAttr tAttr |
  12848.     "Red"
  12849.     majorDv _ v2 redValue - v0 redValue.
  12850.     minorDv _ v1 redValue - v0 redValue.
  12851.     dvdx _ oneOverArea * ((majorDv * minorDy) - (minorDv * majorDy)).
  12852.     dvdy _ oneOverArea * ((majorDx * minorDv) - (majorDv * minorDx)).
  12853.     attributes _ rAttr _ B3DPrimitiveFaceAttributes new.
  12854.     rAttr value: v0 redValue; dvdx: dvdx; dvdy: dvdy.
  12855.     "Green"
  12856.     majorDv _ v2 greenValue - v0 greenValue.
  12857.     minorDv _ v1 greenValue - v0 greenValue.
  12858.     dvdx _ oneOverArea * ((majorDv * minorDy) - (minorDv * majorDy)).
  12859.     dvdy _ oneOverArea * ((majorDx * minorDv) - (majorDv * minorDx)).
  12860.     gAttr _ B3DPrimitiveFaceAttributes new.
  12861.     gAttr value: v0 greenValue; dvdx: dvdx; dvdy: dvdy.
  12862.     rAttr nextAttr: gAttr.
  12863.     "Blue"
  12864.     majorDv _ v2 blueValue - v0 blueValue.
  12865.     minorDv _ v1 blueValue - v0 blueValue.
  12866.     dvdx _ oneOverArea * ((majorDv * minorDy) - (minorDv * majorDy)).
  12867.     dvdy _ oneOverArea * ((majorDx * minorDv) - (majorDv * minorDx)).
  12868.     bAttr _ B3DPrimitiveFaceAttributes new.
  12869.     bAttr value: v0 blueValue; dvdx: dvdx; dvdy: dvdy.
  12870.     gAttr nextAttr: bAttr.
  12871.     "Alpha"
  12872.     majorDv _ v2 alphaValue - v0 alphaValue.
  12873.     minorDv _ v1 alphaValue - v0 alphaValue.
  12874.     dvdx _ oneOverArea * ((majorDv * minorDy) - (minorDv * majorDy)).
  12875.     dvdy _ oneOverArea * ((majorDx * minorDv) - (majorDv * minorDx)).
  12876.     aAttr _ B3DPrimitiveFaceAttributes new.
  12877.     aAttr value: v0 alphaValue; dvdx: dvdx; dvdy: dvdy.
  12878.     bAttr nextAttr: aAttr.
  12879.  
  12880.     "W part"
  12881.     texture == nil ifFalse:[
  12882.         w0 _ v0 rasterPosW. w1 _ v1 rasterPosW. w2 _ v2 rasterPosW.
  12883.         majorDv _ w2 - w0.
  12884.         minorDv _ w1 - w0.
  12885.         dvdx _ oneOverArea * ((majorDv * minorDy) - (minorDv * majorDy)).
  12886.         dvdy _ oneOverArea * ((majorDx * minorDv) - (majorDv * minorDx)).
  12887.         wAttr _ B3DPrimitiveFaceAttributes new.
  12888.         wAttr value: w0; dvdx: dvdx; dvdy: dvdy.
  12889.         aAttr nextAttr: wAttr.
  12890.  
  12891.         baseValue _ v0 texCoordS * w0.
  12892.         majorDv _ (v2 texCoordS * w2) - baseValue.
  12893.         minorDv _ (v1 texCoordS * w1) - baseValue.
  12894.         dvdx _ oneOverArea * ((majorDv * minorDy) - (minorDv * majorDy)).
  12895.         dvdy _ oneOverArea * ((majorDx * minorDv) - (majorDv * minorDx)).
  12896.         sAttr _ B3DPrimitiveFaceAttributes new.
  12897.         sAttr value: baseValue; dvdx: dvdx; dvdy: dvdy.
  12898.         wAttr nextAttr: sAttr.
  12899.  
  12900.         baseValue _ v0 texCoordT * w0.
  12901.         majorDv _ (v2 texCoordT * w2) - baseValue.
  12902.         minorDv _ (v1 texCoordT * w1) - baseValue.
  12903.         dvdx _ oneOverArea * ((majorDv * minorDy) - (minorDv * majorDy)).
  12904.         dvdy _ oneOverArea * ((majorDx * minorDv) - (majorDv * minorDx)).
  12905.         tAttr _ B3DPrimitiveFaceAttributes new.
  12906.         tAttr value: baseValue; dvdx: dvdx; dvdy: dvdy.
  12907.         sAttr nextAttr: tAttr.
  12908.     ].! !
  12909.  
  12910. !B3DPrimitiveFace methodsFor: 'initialize' stamp: 'ar 4/4/1999 21:54'!
  12911. v0: vtx0 v1: vtx1 v2: vtx2
  12912.     v0 _ vtx0.
  12913.     v1 _ vtx1.
  12914.     v2 _ vtx2.
  12915.     flags _ 0.! !
  12916.  
  12917. !B3DPrimitiveFace methodsFor: 'initialize' stamp: 'ar 4/7/1999 01:01'!
  12918. validateDepthSetup
  12919.     oneOverArea = 0.0 ifTrue:[^self].
  12920.     (v0 rasterPosZ - (self zValueAtX: v0 rasterPosX y: v0 rasterPosY)) abs >= 1.0e-10 
  12921.         ifTrue:[self error:'Depth problem'].
  12922.     (v1 rasterPosZ - (self zValueAtX: v1 rasterPosX y: v1 rasterPosY)) abs >= 1.0e-10 
  12923.         ifTrue:[self error:'Depth problem'].
  12924.     (v2 rasterPosZ - (self zValueAtX: v2 rasterPosX y: v2 rasterPosY)) abs >= 1.0e-10 
  12925.         ifTrue:[self error:'Depth problem'].! !
  12926.  
  12927. !B3DPrimitiveFace methodsFor: 'initialize' stamp: 'ar 4/3/1999 21:24'!
  12928. validateVertexOrder
  12929.     (v0 sortsBefore: v1) ifFalse:[self error:'Vertex order problem'].
  12930.     (v0 sortsBefore: v2) ifFalse:[self error:'Vertex order problem'].
  12931.     (v1 sortsBefore: v2) ifFalse:[self error:'Vertex order problem'].! !
  12932.  
  12933. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/6/1999 22:40'!
  12934. attributes
  12935.     ^attributes! !
  12936.  
  12937. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/5/1999 04:13'!
  12938. dzdx
  12939.     ^dzdx! !
  12940.  
  12941. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/5/1999 04:13'!
  12942. dzdy
  12943.     ^dzdy! !
  12944.  
  12945. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:34'!
  12946. flags
  12947.     ^flags! !
  12948.  
  12949. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:34'!
  12950. flags: anInteger
  12951.     flags _ anInteger! !
  12952.  
  12953. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/5/1999 19:05'!
  12954. leftEdge
  12955.     ^leftEdge! !
  12956.  
  12957. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/5/1999 19:06'!
  12958. leftEdge: anEdge
  12959.     leftEdge _ anEdge! !
  12960.  
  12961. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/5/1999 18:22'!
  12962. maxZ
  12963.     ^maxZ! !
  12964.  
  12965. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/5/1999 18:21'!
  12966. minZ
  12967.     ^minZ! !
  12968.  
  12969. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:33'!
  12970. nextFace
  12971.     ^nextFace! !
  12972.  
  12973. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:34'!
  12974. nextFace: aFace
  12975.     nextFace _ aFace! !
  12976.  
  12977. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/5/1999 19:03'!
  12978. oneOverArea
  12979.     ^oneOverArea! !
  12980.  
  12981. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:33'!
  12982. prevFace
  12983.     ^prevFace! !
  12984.  
  12985. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/3/1999 00:34'!
  12986. prevFace: aFace
  12987.     prevFace _ aFace! !
  12988.  
  12989. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/5/1999 19:05'!
  12990. rightEdge
  12991.     ^rightEdge! !
  12992.  
  12993. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/5/1999 19:06'!
  12994. rightEdge: anEdge
  12995.     rightEdge _ anEdge! !
  12996.  
  12997. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/18/1999 06:20'!
  12998. texture
  12999.     ^texture! !
  13000.  
  13001. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/18/1999 06:20'!
  13002. texture: aTexture
  13003.     texture _ aTexture! !
  13004.  
  13005. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/3/1999 21:32'!
  13006. vertex0
  13007.     ^v0! !
  13008.  
  13009. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/3/1999 21:32'!
  13010. vertex1
  13011.     ^v1! !
  13012.  
  13013. !B3DPrimitiveFace methodsFor: 'accessing' stamp: 'ar 4/3/1999 21:32'!
  13014. vertex2
  13015.     ^v2! !
  13016.  
  13017. !B3DPrimitiveFace methodsFor: 'processing' stamp: 'ar 4/18/1999 06:34'!
  13018. attrValue: attr atX: xValue y: yValue
  13019.     "Return the value of the attribute at position xValue@yValue"
  13020.     ^attr valueAtX: (xValue - v0 rasterPosX) y: (yValue - v0 rasterPosY).! !
  13021.  
  13022. !B3DPrimitiveFace methodsFor: 'processing' stamp: 'ar 4/8/1999 04:31'!
  13023. zValueAtX: xValue y: yValue
  13024.     "Return the z value of the receiver at position xValue@yValue"
  13025.     ^v0 rasterPosZ +
  13026.         (yValue - v0 rasterPosY * dzdy) +
  13027.         (xValue - v0 rasterPosX * dzdx)! !
  13028.  
  13029. !B3DPrimitiveFace methodsFor: 'printing' stamp: 'ar 4/5/1999 01:22'!
  13030. printOn: aStream
  13031.     super printOn: aStream.
  13032.     aStream
  13033.         nextPut:$(;
  13034.         print: (v0 windowPos bitShiftPoint:-12);
  13035.         nextPutAll:' - ';
  13036.         print: (v1 windowPos bitShiftPoint: -12);
  13037.         nextPutAll:' - ';
  13038.         print: (v2 windowPos bitShiftPoint: -12);
  13039.         nextPut:$).! !
  13040.  
  13041. !B3DPrimitiveFaceAttributes methodsFor: 'accessing' stamp: 'ar 4/18/1999 06:33'!
  13042. dvdx
  13043.     ^dvdx! !
  13044.  
  13045. !B3DPrimitiveFaceAttributes methodsFor: 'accessing' stamp: 'ar 4/18/1999 06:33'!
  13046. dvdx: aNumber
  13047.     dvdx _ aNumber! !
  13048.  
  13049. !B3DPrimitiveFaceAttributes methodsFor: 'accessing' stamp: 'ar 4/18/1999 06:33'!
  13050. dvdy
  13051.     ^dvdy! !
  13052.  
  13053. !B3DPrimitiveFaceAttributes methodsFor: 'accessing' stamp: 'ar 4/18/1999 06:33'!
  13054. dvdy: aNumber
  13055.     dvdy _ aNumber! !
  13056.  
  13057. !B3DPrimitiveFaceAttributes methodsFor: 'accessing' stamp: 'ar 4/18/1999 06:32'!
  13058. nextAttr
  13059.     ^nextAttr! !
  13060.  
  13061. !B3DPrimitiveFaceAttributes methodsFor: 'accessing' stamp: 'ar 4/18/1999 06:32'!
  13062. nextAttr: attr
  13063.     nextAttr _ attr.! !
  13064.  
  13065. !B3DPrimitiveFaceAttributes methodsFor: 'accessing' stamp: 'ar 4/18/1999 06:32'!
  13066. value
  13067.     ^value! !
  13068.  
  13069. !B3DPrimitiveFaceAttributes methodsFor: 'accessing' stamp: 'ar 4/18/1999 06:32'!
  13070. value: aNumber
  13071.     value _ aNumber! !
  13072.  
  13073. !B3DPrimitiveFaceAttributes methodsFor: 'accessing' stamp: 'ar 4/18/1999 06:34'!
  13074. valueAtX: xValue y: yValue
  13075.     "Return the value of the attribute at position xValue@yValue"
  13076.     ^value + (yValue * dvdy) + (xValue * dvdx)! !
  13077.  
  13078. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 03:51'!
  13079. attenuation
  13080.     "Return the light attenuation.
  13081.     This member is only valid if the light is attenuated."
  13082.     ^B3DLightAttenuation
  13083.         constant: self constantAttenuation
  13084.         linear: self linearAttenuation
  13085.         squared: self squaredAttenuation! !
  13086.  
  13087. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 03:52'!
  13088. attenuation: aLightAttenuation
  13089.     "Set the light attenuation.
  13090.     This member is only valid if the light is attenuated."
  13091.     self constantAttenuation: aLightAttenuation constantPart.
  13092.     self linearAttenuation: aLightAttenuation linearPart.
  13093.     self squaredAttenuation: aLightAttenuation squaredPart.! !
  13094.  
  13095. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 03:47'!
  13096. direction
  13097.     "Return the direction of the light.
  13098.     This member is valid only if the light is not positional 
  13099.     (e.g., the direction must be computed for every vertex)"
  13100.     ^B3DVector3
  13101.         x: self directionX
  13102.         y: self directionY
  13103.         z: self directionZ! !
  13104.  
  13105. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 03:49'!
  13106. direction: aB3DVector
  13107.     "Set the direction of the light.
  13108.     This member is valid only if the light is positional 
  13109.     (e.g., the direction must be computed for every vertex)"
  13110.     self directionX: aB3DVector x.
  13111.     self directionY: aB3DVector y.
  13112.     self directionZ: aB3DVector z.! !
  13113.  
  13114. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 22:17'!
  13115. flags
  13116.     ^self wordAt: PrimLightFlags+1! !
  13117.  
  13118. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 22:17'!
  13119. flags: aValue
  13120.     ^self wordAt: PrimLightFlags+1 put: aValue! !
  13121.  
  13122. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 03:49'!
  13123. position
  13124.     "Return the position of the light.
  13125.     This member is valid only if the light is not positional 
  13126.     (e.g., the direction must be computed for every vertex)"
  13127.     ^B3DVector3
  13128.         x: self positionX
  13129.         y: self positionY
  13130.         z: self positionZ! !
  13131.  
  13132. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 03:48'!
  13133. position: aB3DVector
  13134.     "Set the position of the light.
  13135.     This member is valid only if the light is positional 
  13136.     (e.g., the direction must be computed for every vertex)"
  13137.     self positionX: aB3DVector x.
  13138.     self positionY: aB3DVector y.
  13139.     self positionZ: aB3DVector z.! !
  13140.  
  13141. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 22:17'!
  13142. spotDeltaCos
  13143.     ^self floatAt: SpotLightDeltaCos+1! !
  13144.  
  13145. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 22:17'!
  13146. spotDeltaCos: aFloat
  13147.     ^self floatAt: SpotLightDeltaCos+1 put: aFloat! !
  13148.  
  13149. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 22:17'!
  13150. spotExponent
  13151.     ^self floatAt: SpotLightExponent+1! !
  13152.  
  13153. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 22:17'!
  13154. spotExponent: aFloat
  13155.     ^self floatAt: SpotLightExponent+1 put: aFloat! !
  13156.  
  13157. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 22:18'!
  13158. spotMaxCos
  13159.     ^self floatAt: SpotLightMaxCos+1! !
  13160.  
  13161. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 22:18'!
  13162. spotMaxCos: aFloat
  13163.     ^self floatAt: SpotLightMaxCos+1 put: aFloat! !
  13164.  
  13165. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 22:18'!
  13166. spotMinCos
  13167.     ^self floatAt: SpotLightMinCos+1! !
  13168.  
  13169. !B3DPrimitiveLight methodsFor: 'accessing' stamp: 'ar 2/15/1999 22:18'!
  13170. spotMinCos: aFloat
  13171.     ^self floatAt: SpotLightMinCos+1 put: aFloat! !
  13172.  
  13173. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:14'!
  13174. constantAttenuation
  13175.     ^self floatAt: PrimLightAttenuationConstant+1! !
  13176.  
  13177. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:14'!
  13178. constantAttenuation: aFloat
  13179.     ^self floatAt: PrimLightAttenuationConstant+1 put: aFloat! !
  13180.  
  13181. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:14'!
  13182. directionX
  13183.     ^self floatAt: PrimLightDirectionX+1! !
  13184.  
  13185. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:14'!
  13186. directionX: aFloat
  13187.     ^self floatAt: PrimLightDirectionX+1 put: aFloat! !
  13188.  
  13189. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:14'!
  13190. directionY
  13191.     ^self floatAt: PrimLightDirectionY+1! !
  13192.  
  13193. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:15'!
  13194. directionY: aFloat
  13195.     ^self floatAt: PrimLightDirectionY+1 put: aFloat! !
  13196.  
  13197. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:15'!
  13198. directionZ
  13199.     ^self floatAt: PrimLightDirectionZ+1! !
  13200.  
  13201. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:15'!
  13202. directionZ: aFloat
  13203.     ^self floatAt: PrimLightDirectionZ+1 put: aFloat! !
  13204.  
  13205. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:15'!
  13206. linearAttenuation
  13207.     ^self floatAt: PrimLightAttenuationLinear+1! !
  13208.  
  13209. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:15'!
  13210. linearAttenuation: aFloat
  13211.     ^self floatAt: PrimLightAttenuationLinear+1 put: aFloat! !
  13212.  
  13213. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:15'!
  13214. positionX
  13215.     ^self floatAt: PrimLightPositionX+1! !
  13216.  
  13217. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:15'!
  13218. positionX: aFloat
  13219.     ^self floatAt: PrimLightPositionX+1 put: aFloat! !
  13220.  
  13221. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:15'!
  13222. positionY
  13223.     ^self floatAt: PrimLightPositionY+1! !
  13224.  
  13225. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:15'!
  13226. positionY: aFloat
  13227.     ^self floatAt: PrimLightPositionY+1 put: aFloat! !
  13228.  
  13229. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:15'!
  13230. positionZ
  13231.     ^self floatAt: PrimLightPositionZ+1! !
  13232.  
  13233. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:15'!
  13234. positionZ: aFloat
  13235.     ^self floatAt: PrimLightPositionZ+1 put: aFloat! !
  13236.  
  13237. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:15'!
  13238. squaredAttenuation
  13239.     ^self floatAt: PrimLightAttenuationSquared+1! !
  13240.  
  13241. !B3DPrimitiveLight methodsFor: 'element access' stamp: 'ar 2/15/1999 22:15'!
  13242. squaredAttenuation: aFloat
  13243.     ^self floatAt: PrimLightAttenuationSquared+1 put: aFloat! !
  13244.  
  13245. !B3DPrimitiveLight class methodsFor: 'instance creation' stamp: 'ar 2/15/1999 22:11'!
  13246. numElements
  13247.     ^PrimLightSize! !
  13248.  
  13249. !B3DPrimitiveObject methodsFor: 'accessing' stamp: 'ar 4/18/1999 05:43'!
  13250. bounds
  13251.     ^bounds! !
  13252.  
  13253. !B3DPrimitiveObject methodsFor: 'accessing' stamp: 'ar 4/18/1999 04:49'!
  13254. faces
  13255.     ^faces! !
  13256.  
  13257. !B3DPrimitiveObject methodsFor: 'accessing' stamp: 'ar 4/18/1999 04:49'!
  13258. faces: anArray
  13259.     faces _ anArray! !
  13260.  
  13261. !B3DPrimitiveObject methodsFor: 'accessing' stamp: 'ar 4/18/1999 05:44'!
  13262. nextObj
  13263.     ^next! !
  13264.  
  13265. !B3DPrimitiveObject methodsFor: 'accessing' stamp: 'ar 4/18/1999 05:44'!
  13266. nextObj: obj
  13267.     next _ obj! !
  13268.  
  13269. !B3DPrimitiveObject methodsFor: 'accessing' stamp: 'ar 4/18/1999 05:44'!
  13270. prevObj
  13271.     ^prev! !
  13272.  
  13273. !B3DPrimitiveObject methodsFor: 'accessing' stamp: 'ar 4/18/1999 05:45'!
  13274. prevObj: obj
  13275.     prev _ obj! !
  13276.  
  13277. !B3DPrimitiveObject methodsFor: 'accessing' stamp: 'ar 4/18/1999 06:56'!
  13278. texture
  13279.     ^texture! !
  13280.  
  13281. !B3DPrimitiveObject methodsFor: 'accessing' stamp: 'ar 4/18/1999 06:56'!
  13282. texture: aTexture
  13283.     texture _ aTexture! !
  13284.  
  13285. !B3DPrimitiveObject methodsFor: 'accessing' stamp: 'ar 4/18/1999 04:49'!
  13286. vertices
  13287.     ^vertices! !
  13288.  
  13289. !B3DPrimitiveObject methodsFor: 'accessing' stamp: 'ar 4/18/1999 04:49'!
  13290. vertices: anArray
  13291.     vertices _ anArray! !
  13292.  
  13293. !B3DPrimitiveObject methodsFor: 'processing' stamp: 'ar 4/18/1999 05:44'!
  13294. mapVertices: viewport
  13295.     "Map all the vertices in the receiver"
  13296.     | xOfs yOfs xScale yScale w x y z scaledX scaledY first |
  13297.     xOfs _ (viewport origin x + viewport corner x) * 0.5 - 0.5.
  13298.     yOfs _ (viewport origin y + viewport corner y) * 0.5 - 0.5.
  13299.     xScale _ (viewport corner x - viewport origin x) * 0.5.
  13300.     yScale _ (viewport corner y - viewport origin y) * -0.5.
  13301.     bounds _ 16r3FFFFFFF asPoint extent: 0@0.
  13302.     minZ _ maxZ _ 0.0.
  13303.     first _ true.
  13304.     vertices do:[:vtx|
  13305.         w _ vtx rasterPosW.
  13306.         w = 0.0 ifFalse:[w _ 1.0 / w].
  13307.         x _ vtx rasterPosX * w * xScale + xOfs.
  13308.         y _ vtx rasterPosY * w * yScale + yOfs.
  13309.         z _ vtx rasterPosZ * w.
  13310.         vtx rasterPosW: w.
  13311.         vtx rasterPosZ: z.
  13312.         scaledX _ (x * 4096.0) asInteger.
  13313.         scaledY _ (y * 4096.0) asInteger.
  13314.         vtx windowPosX: scaledX.
  13315.         vtx windowPosY: scaledY.
  13316.         true ifTrue:[
  13317.             vtx rasterPosX: scaledX / 4096.0.
  13318.             vtx rasterPosY: scaledY / 4096.0.
  13319.         ] ifFalse:[
  13320.             vtx rasterPosX: x.
  13321.             vtx rasterPosY: y.
  13322.         ].
  13323.         first ifTrue:[
  13324.             bounds _ scaledX@scaledY extent: 0@0.
  13325.             minZ _ maxZ _ z.
  13326.             first _ false.
  13327.         ] ifFalse:[
  13328.             bounds _ bounds encompass: scaledX@scaledY.
  13329.             minZ _ minZ min: z. 
  13330.             maxZ _ maxZ max: z.
  13331.         ].
  13332.     ].
  13333.     bounds _ (bounds origin bitShiftPoint: -12) corner: (bounds corner bitShiftPoint: -12).! !
  13334.  
  13335. !B3DPrimitiveObject methodsFor: 'processing' stamp: 'ar 4/18/1999 05:12'!
  13336. setupVertexOrder
  13337.     faces do:[:face| self setupVertexOrder: face].! !
  13338.  
  13339. !B3DPrimitiveObject methodsFor: 'processing' stamp: 'ar 4/18/1999 05:10'!
  13340. setupVertexOrder: face
  13341.     | p1 p2 i1 i2 i3 p3  |
  13342.     i1 _ face p1Index.
  13343.     i2 _ face p2Index.
  13344.     i3 _ face p3Index.
  13345.     p1 _ vertices at: i1.
  13346.     p2 _ vertices at: i2.
  13347.     p3 _ vertices at: i3.
  13348.     (p1 sortsBefore: p2) ifTrue:[
  13349.         (p2 sortsBefore: p3) ifTrue:[
  13350.             face p1Index: i1; p2Index: i2; p3Index: i3.
  13351.         ] ifFalse:[
  13352.             (p1 sortsBefore: p3)
  13353.                 ifTrue:[face p1Index: i1; p2Index: i3; p3Index: i2]
  13354.                 ifFalse:[face p1Index: i3; p2Index: i1; p3Index: i2]
  13355.         ].
  13356.     ] ifFalse:[
  13357.         (p1 sortsBefore: p3) ifTrue:[
  13358.             face p1Index: i2; p2Index: i1; p3Index: i3.
  13359.         ] ifFalse:[
  13360.             (p2 sortsBefore: p3)
  13361.                 ifTrue:[face p1Index: i2; p2Index: i3; p3Index: i1]
  13362.                 ifFalse:[face p1Index: i3; p2Index: i2; p3Index: i1]
  13363.         ]
  13364.     ].
  13365.     B3DScanner doDebug ifTrue:[
  13366.         p1 _ vertices at: face p1Index.
  13367.         p2 _ vertices at: face p2Index.
  13368.         p3 _ vertices at: face p3Index.
  13369.         ((p1 sortsBefore: p2) and:[(p2 sortsBefore: p3) and:[p1 sortsBefore: p3]])
  13370.             ifFalse:[self error:'Vertex order problem'].
  13371.     ].
  13372. ! !
  13373.  
  13374. !B3DPrimitiveObject methodsFor: 'processing' stamp: 'ar 4/18/1999 05:13'!
  13375. sortInitialFaces
  13376.     faces _ faces sortBy:[:face1 :face2| (vertices at: face1 p1Index) sortsBefore: (vertices at: face2 p1Index)].! !
  13377.  
  13378. !B3DPrimitiveObject methodsFor: 'initialize' stamp: 'ar 4/18/1999 05:22'!
  13379. reset
  13380.     start _ 0.! !
  13381.  
  13382. !B3DPrimitiveObject methodsFor: 'streaming' stamp: 'ar 4/18/1999 05:26'!
  13383. atEnd
  13384.     ^start >= faces size! !
  13385.  
  13386. !B3DPrimitiveObject methodsFor: 'streaming' stamp: 'ar 4/18/1999 06:55'!
  13387. next
  13388.     | iFace face |
  13389.     iFace _ faces at: (start _ start + 1).
  13390.     face _ B3DPrimitiveFace new.
  13391.     face 
  13392.         v0: (vertices at: iFace p1Index)
  13393.         v1: (vertices at: iFace p2Index)
  13394.         v2: (vertices at: iFace p3Index).
  13395.     face texture: texture.
  13396.     face initializePass1.
  13397.     B3DScanner doDebug ifTrue:[
  13398.         face validateVertexOrder.
  13399.         face validateDepthSetup].
  13400.     ^face! !
  13401.  
  13402. !B3DPrimitiveObject methodsFor: 'streaming' stamp: 'ar 4/18/1999 05:25'!
  13403. peekY
  13404.     ^(vertices at: (faces at: start+1) p1Index) windowPosY! !
  13405.  
  13406. !B3DPrimitiveRasterizer methodsFor: 'initialize' stamp: 'ar 5/26/2000 15:41'!
  13407. clipRect: aRectangle
  13408.     super clipRect: aRectangle.
  13409.     state bitBlt clipRect: aRectangle.! !
  13410.  
  13411. !B3DPrimitiveRasterizer methodsFor: 'initialize' stamp: 'ar 4/17/1999 21:10'!
  13412. flush
  13413.     self mainLoop.! !
  13414.  
  13415. !B3DPrimitiveRasterizer methodsFor: 'initialize' stamp: 'ar 4/16/1999 07:54'!
  13416. initialize
  13417.     super initialize.
  13418.     primObjects _ WriteStream on: (Array new: 100).
  13419.     state _ B3DPrimitiveRasterizerState new.
  13420.     state initialize.
  13421.     textures _ IdentityDictionary new: 33.! !
  13422.  
  13423. !B3DPrimitiveRasterizer methodsFor: 'initialize' stamp: 'ar 4/10/1999 22:53'!
  13424. reset
  13425.     super reset.
  13426.     state reset.! !
  13427.  
  13428. !B3DPrimitiveRasterizer methodsFor: 'initialize' stamp: 'ar 5/28/2000 12:16'!
  13429. target: aForm
  13430.     | bb span sourceForm |
  13431.     super target: aForm.
  13432.     target ifNil:[^self].
  13433.     "Note: span must be Bitmap since software rasterizer expects canonical RGBA for now"
  13434.     span _ Bitmap new: 2048.
  13435.     sourceForm _ Form extent: span size@1 depth: 32 bits: span.
  13436.     bb _ BitBlt current toForm: target.
  13437.     self class primitiveSetBitBltPlugin: bb getPluginName.
  13438.     bb sourceForm: sourceForm.
  13439.     bb isFXBlt ifTrue:[
  13440.         "Specific setup for FXBlt is necessary"
  13441.         bb colorMap: (sourceForm colormapIfNeededFor: target).
  13442.         bb combinationRule: (target depth >= 8 ifTrue:[34] ifFalse:[Form paint]).
  13443.     ] ifFalse:[
  13444.         bb colorMap: (sourceForm colormapIfNeededForDepth: target depth).
  13445.         bb combinationRule: (target depth >= 8 ifTrue:[34] ifFalse:[Form paint]).
  13446.     ].
  13447.     bb destX: 0; destY: 0; sourceX: 0; sourceY: 0; width: 1; height: 1.
  13448.     state spanBuffer: span.
  13449.     state bitBlt: bb.! !
  13450.  
  13451. !B3DPrimitiveRasterizer methodsFor: 'testing' stamp: 'ar 4/14/1999 02:08'!
  13452. needsClip
  13453.     ^true! !
  13454.  
  13455. !B3DPrimitiveRasterizer methodsFor: 'processing' stamp: 'ar 11/7/1999 18:47'!
  13456. addPrimitiveObject: vb ofSize: objSize
  13457.     | obj textureIndex |
  13458.     texture == nil
  13459.         ifTrue:[textureIndex _ 0]
  13460.         ifFalse:[textureIndex _ textures at: texture ifAbsentPut:[textures size+1]].
  13461.     obj _ B3DPrimitiveRasterizerData new: objSize.
  13462.     self primAddObject: obj
  13463.         primitive: vb primitive
  13464.         vertexArray: vb vertexArray
  13465.         size: vb vertexCount
  13466.         indexArray: vb indexArray
  13467.         size: vb indexCount
  13468.         viewport: viewport
  13469.         textureIndex: textureIndex.
  13470.     primObjects nextPut: obj.
  13471.     "AAARRRRGGGGGHHHH - we should do this differently!!!!!!!!"
  13472.     vbBounds _ (obj integerAt: 9) @ (obj integerAt: 11) corner: (obj integerAt: 10) @ (obj integerAt: 12).! !
  13473.  
  13474. !B3DPrimitiveRasterizer methodsFor: 'processing' stamp: 'ar 5/26/2000 15:41'!
  13475. debugDrawVB: vb
  13476.     | vtx idx1 idx2 idx3 v1 v2 v3 vp myCanvas |
  13477.     myCanvas _ target getCanvas.
  13478.     vp _ viewport clone.
  13479.     vtx _ Array new: vb vertexCount.
  13480.     vb vertexArray upTo: vb vertexCount doWithIndex:[:v :i|
  13481.         vtx at: i put: (vp mapVertex4: v rasterPos).
  13482.     ].
  13483.     1 to: vb indexCount-1 by: 3 do:[:i|
  13484.         idx1 _ vb indexArray at: i.
  13485.         idx2 _ vb indexArray at: i+1.
  13486.         idx3 _ vb indexArray at: i+2.
  13487.         idx1 = 0 ifFalse:[
  13488.             v1 _ vtx at: idx1.
  13489.             v2 _ vtx at: idx2.
  13490.             v3 _ vtx at: idx3.
  13491.             myCanvas line: v1 to: v2 width: 1 color: Color black.
  13492.             myCanvas line: v2 to: v3 width: 1 color: Color black.
  13493.             myCanvas line: v3 to: v1 width: 1 color: Color black.
  13494.         ].
  13495.     ].! !
  13496.  
  13497. !B3DPrimitiveRasterizer methodsFor: 'processing' stamp: 'ar 11/7/1999 22:25'!
  13498. mainLoop
  13499.     "Do the actual rasterization"
  13500.     | errCode objects textureArray |
  13501.     objects _ primObjects contents.
  13502.     objects size = 0 ifTrue:[^self]. "Nothing to do"
  13503.     textureArray _ Array new: textures size.
  13504.     textures associationsDo:[:assoc| textureArray at: assoc value put: assoc key].
  13505.     state initObjects: objects size.
  13506.     state initTextures: textureArray size.
  13507.     textureArray do:[:tex| tex unhibernate].
  13508.     [errCode _ self primStartRasterizer: state objects: objects textures: textureArray.
  13509.     errCode = 0] whileFalse:[
  13510.         "Not yet finished"
  13511.         self processErrorCode: (errCode bitAnd: 255).
  13512.         state reset].
  13513.     primObjects reset.
  13514.     textures _ IdentityDictionary new: textures capacity.
  13515.     false ifTrue:[self printSpaceUsage: objects].
  13516. ! !
  13517.  
  13518. !B3DPrimitiveRasterizer methodsFor: 'processing' stamp: 'ar 4/12/1999 02:32'!
  13519. processErrorCode: errCode
  13520.     errCode = 0 ifTrue:[^true]. "This is allowed!!"
  13521.     (errCode = B3DNoMoreEdges) 
  13522.         ifTrue:[^state growEdges].
  13523.     (errCode = B3DNoMoreFaces)
  13524.         ifTrue:[^state growFaces].
  13525.     (errCode = B3DNoMoreAttrs)
  13526.         ifTrue:[^state growAttrs].
  13527.     (errCode = B3DNoMoreAET)
  13528.         ifTrue:[^state growAET].
  13529.     (errCode = B3DNoMoreAdded)
  13530.         ifTrue:[^state growAdded].
  13531.     self error:'Unknown rasterizer error code ', errCode printString.! !
  13532.  
  13533. !B3DPrimitiveRasterizer methodsFor: 'processing' stamp: 'ar 4/17/1999 20:29'!
  13534. processIndexedLines: vb
  13535.     "Process an indexed line set"
  13536.     self error:'Indexed lines are not yet implemented'! !
  13537.  
  13538. !B3DPrimitiveRasterizer methodsFor: 'processing' stamp: 'ar 9/10/1999 14:58'!
  13539. processIndexedQuads: vb
  13540.     "Process an indexed quad set"
  13541.     | objSize |
  13542.     objSize _ self primObjectSize + (vb vertexCount + 1 * PrimVertexSize) + (vb indexCount).
  13543.     self addPrimitiveObject: vb ofSize: objSize.! !
  13544.  
  13545. !B3DPrimitiveRasterizer methodsFor: 'processing' stamp: 'ar 9/10/1999 14:59'!
  13546. processIndexedTriangles: vb
  13547.     | objSize |
  13548.     objSize _ self primObjectSize + (vb vertexCount + 1 * PrimVertexSize) + (vb indexCount).
  13549.     self addPrimitiveObject: vb ofSize: objSize.! !
  13550.  
  13551. !B3DPrimitiveRasterizer methodsFor: 'processing' stamp: 'ar 4/17/1999 20:29'!
  13552. processLineLoop: vb
  13553.     "Process a closed line defined by the vertex buffer"
  13554.     self error:'Lines are not yet implemented'! !
  13555.  
  13556. !B3DPrimitiveRasterizer methodsFor: 'processing' stamp: 'ar 4/17/1999 20:29'!
  13557. processLines: vb
  13558.     "Process a series of lines defined by each two points the vertex buffer"
  13559.     self error:'Lines are not yet implemented'! !
  13560.  
  13561. !B3DPrimitiveRasterizer methodsFor: 'processing' stamp: 'ar 4/17/1999 20:30'!
  13562. processPoints: vertexBuffer
  13563.     "Process a series of points defined by the vertex buffer"
  13564.     self error:'Points are not yet implemented'! !
  13565.  
  13566. !B3DPrimitiveRasterizer methodsFor: 'processing' stamp: 'ar 4/17/1999 21:02'!
  13567. processPolygon: vb
  13568.     "Process a polygon defined by the vertex buffer"
  13569.     | objSize |
  13570.     objSize _ self primObjectSize + (vb vertexCount * PrimVertexSize) + (vb vertexCount - 2 * 3).
  13571.     self addPrimitiveObject: vb ofSize: objSize.! !
  13572.  
  13573. !B3DPrimitiveRasterizer methodsFor: 'primitives' stamp: 'ar 4/14/1999 05:12'!
  13574. primAddObject: obj primitive: primitive vertexArray: vertexArray size: vertexCount indexArray: indexArray size: indexCount viewport: vp textureIndex: txIndex
  13575.     <primitive:'b3dInitPrimitiveObject' module:'Squeak3D'>
  13576.     ^self primitiveFailed! !
  13577.  
  13578. !B3DPrimitiveRasterizer methodsFor: 'primitives' stamp: 'ar 4/12/1999 02:17'!
  13579. primObjectSize
  13580.     <primitive: 'b3dPrimitiveObjectSize' module:'Squeak3D'>
  13581.     ^self primitiveFailed! !
  13582.  
  13583. !B3DPrimitiveRasterizer methodsFor: 'primitives' stamp: 'ar 4/14/1999 05:18'!
  13584. primStartRasterizer: primState objects: primitiveObjects textures: textureArray
  13585.     "Primitive. Start the rasterizer. Return an error code."
  13586.     <primitive:'b3dStartRasterizer' module:'Squeak3D'>
  13587.     ^self primitiveFailed! !
  13588.  
  13589. !B3DPrimitiveRasterizer methodsFor: 'private' stamp: 'ar 4/13/1999 02:13'!
  13590. printSpaceUsage: objects
  13591.     "Print out the maximum space used for processing the given objects"
  13592.     | spaceUsed |
  13593.     spaceUsed _ state spaceUsed.
  13594.     objects do:[:obj| spaceUsed _ spaceUsed + obj basicSize].
  13595.     spaceUsed _ spaceUsed * 4.
  13596.     Transcript cr; nextPutAll: spaceUsed asStringWithCommas; nextPutAll:' bytes max working set'; endEntry.! !
  13597.  
  13598. !B3DPrimitiveRasterizer class methodsFor: 'class initialization' stamp: 'ar 4/13/1999 01:52'!
  13599. initialize
  13600.     "B3DPrimitiveRasterizer initialize"
  13601.     B3DNoMoreEdges _ 1.
  13602.     B3DNoMoreFaces _ 2.
  13603.     B3DNoMoreAttrs _ 3.
  13604.     B3DNoMoreAET _ 4.
  13605.     B3DNoMoreAdded _ 5.! !
  13606.  
  13607. !B3DPrimitiveRasterizer class methodsFor: 'accessing' stamp: 'ar 4/12/1999 03:46'!
  13608. version
  13609.     "B3DPrimitiveRasterizer version"
  13610.     <primitive:'b3dRasterizerVersion' module:'Squeak3D'>
  13611.     ^0! !
  13612.  
  13613. !B3DPrimitiveRasterizer class methodsFor: 'testing' stamp: 'ar 4/12/1999 03:48'!
  13614. isAvailable
  13615.     ^self version > 0! !
  13616.  
  13617. !B3DPrimitiveRasterizer class methodsFor: 'private' stamp: 'ar 5/28/2000 22:17'!
  13618. primitiveSetBitBltPlugin: pluginName
  13619.     <primitive: 'primitiveSetBitBltPlugin' module: 'Squeak3D'>
  13620.     ^nil! !
  13621.  
  13622. Instances of this class represent data on the primitive level. The major reason for the existance of this class is that all memory needed by the rasterizer is allocated from Smalltalk code[*]. Instances of this class should not be modified from Smalltalk code - they may contain pointers to other memory locations and thus modification of these instances could easily break the system.
  13623.  
  13624. [*] This is for two reasons:
  13625.     * Some systems (e.g., Mac) don't have the necessary allocation facilities from the primitive level (This REALLY sucks. We have 1999 and MacOS 8.5.1 still has static memory allocation!!)
  13626.     * Allocation from Smalltalk allows us to share memory between Smalltalk and C code, take advantage of GCs if the physically available space is small (e.g., on PDAs) as well as gracefully failing if there is no memory left (e.g., by signalling the low space condition).
  13627. !
  13628. !B3DPrimitiveRasterizerData methodsFor: 'accessing' stamp: 'ar 4/10/1999 05:36'!
  13629. at: index put: value
  13630.     "See the class comment"
  13631.     ^self error:'You must not modify primitive level data'! !
  13632.  
  13633. !B3DPrimitiveRasterizerData methodsFor: 'accessing' stamp: 'ar 11/7/1999 18:09'!
  13634. integerAt: index
  13635.     "Return the integer at the given index"
  13636.     | word |
  13637.     word _ self basicAt: index.
  13638.     word < 16r3FFFFFFF ifTrue:[^word]. "Avoid LargeInteger computations"
  13639.     ^word >= 16r80000000    "Negative?!!"
  13640.         ifTrue:["word - 16r100000000"
  13641.                 (word bitInvert32 + 1) negated]
  13642.         ifFalse:[word]! !
  13643.  
  13644. !B3DPrimitiveRasterizerData methodsFor: 'private' stamp: 'ar 4/12/1999 02:36'!
  13645. replaceFrom: start to: stop with: replacement startingAt: repStart
  13646.     "Private. Used for growing rasterizer data only."
  13647.     <primitive: 105>
  13648.     ^self primitiveFailed! !
  13649.  
  13650. This class represents a set of objects that are known to the primitive level rasterizer. It should not be modified unless you know *exactly* what you're doing. The instance variables could actually be indexed but I decided to give them names for readability.
  13651.  
  13652. Instance variables:
  13653.     faceAlloc    <B3DPrimitiveRasterizerData>    - Source for primitive level face allocation.
  13654.     edgeAlloc    <B3DPrimitiveRasterizerData>    - Source for primitive level edge allocation.
  13655.     attrAlloc    <B3DPrimitiveRasterizerData>    - Source for primitive level attribute allocation.
  13656.     aet            <B3DPrimitiveRasterizerData>    - Primitive level active edge table.
  13657.     addedEdges    <B3DPrimitiveRasterizerData>    - Primitive level temporary edge storage.
  13658.     fillList        <B3DPrimitiveRasterizerData>    - Primitive level fill list.
  13659.     objects        <B3DPrimitiveRasterizerData> - Primitive level list of objects.
  13660.     textures        <B3DPrimitiveRasterizerData> - Primitive level lists of textures.
  13661.     spanBuffer    <Bitmap>                        - 32bit bitmap to render into
  13662.     bitBlt        <BitBlt>                        - Final output device
  13663. !
  13664. !B3DPrimitiveRasterizerState methodsFor: 'initialize' stamp: 'ar 4/14/1999 05:14'!
  13665. initObjects: nObjects
  13666.     objects _ B3DPrimitiveRasterizerData new: nObjects! !
  13667.  
  13668. !B3DPrimitiveRasterizerState methodsFor: 'initialize' stamp: 'ar 4/14/1999 05:13'!
  13669. initTextures: nTextures
  13670.     textures _ B3DPrimitiveRasterizerData new: (self primTextureSize * nTextures).! !
  13671.  
  13672. !B3DPrimitiveRasterizerState methodsFor: 'initialize' stamp: 'ar 4/13/1999 06:29'!
  13673. initialize
  13674.     faceAlloc ifNil:[faceAlloc _ B3DPrimitiveRasterizerData new: 32768].
  13675.     edgeAlloc ifNil:[edgeAlloc _ B3DPrimitiveRasterizerData new: 16384].
  13676.     attrAlloc ifNil:[attrAlloc _ B3DPrimitiveRasterizerData new: 4096].
  13677.     aet ifNil:[aet _ B3DPrimitiveRasterizerData new: 4096].
  13678.     addedEdges ifNil:[addedEdges _ B3DPrimitiveRasterizerData new: 4096].
  13679.     fillList ifNil:[fillList _ B3DPrimitiveRasterizerData new: 32].
  13680.     self primInitializeBuffers.! !
  13681.  
  13682. !B3DPrimitiveRasterizerState methodsFor: 'initialize' stamp: 'ar 4/11/1999 23:47'!
  13683. reset
  13684.     self primInitializeBuffers.! !
  13685.  
  13686. !B3DPrimitiveRasterizerState methodsFor: 'accessing' stamp: 'ar 4/13/1999 00:10'!
  13687. bitBlt
  13688.     ^bitBlt! !
  13689.  
  13690. !B3DPrimitiveRasterizerState methodsFor: 'accessing' stamp: 'ar 4/13/1999 00:10'!
  13691. bitBlt: aBitBlt
  13692.     bitBlt _ aBitBlt.! !
  13693.  
  13694. !B3DPrimitiveRasterizerState methodsFor: 'accessing' stamp: 'ar 4/13/1999 02:09'!
  13695. spaceUsed
  13696.     ^faceAlloc basicSize + edgeAlloc basicSize + attrAlloc basicSize + aet basicSize + addedEdges basicSize + fillList basicSize + objects basicSize + spanBuffer basicSize! !
  13697.  
  13698. !B3DPrimitiveRasterizerState methodsFor: 'accessing' stamp: 'ar 4/13/1999 00:10'!
  13699. spanBuffer
  13700.     ^spanBuffer! !
  13701.  
  13702. !B3DPrimitiveRasterizerState methodsFor: 'accessing' stamp: 'ar 4/13/1999 00:10'!
  13703. spanBuffer: aBitmap
  13704.     spanBuffer _ aBitmap.! !
  13705.  
  13706. !B3DPrimitiveRasterizerState methodsFor: 'growing' stamp: 'ar 4/14/1999 01:45'!
  13707. grow: anArray
  13708.     | newArray |
  13709.     newArray _ anArray species new: anArray size + (anArray size // 4 max: 100).
  13710.     newArray replaceFrom: 1 to: anArray size with: anArray startingAt: 1.
  13711.     ^newArray! !
  13712.  
  13713. !B3DPrimitiveRasterizerState methodsFor: 'growing' stamp: 'ar 4/13/1999 06:30'!
  13714. growAET
  13715.     "Transcript cr; show:'Growing AET'."
  13716.     aet _ self grow: aet.! !
  13717.  
  13718. !B3DPrimitiveRasterizerState methodsFor: 'growing' stamp: 'ar 4/13/1999 06:30'!
  13719. growAdded
  13720.     "Transcript cr; show:'Growing addedEdges'."
  13721.     aet _ self grow: addedEdges.! !
  13722.  
  13723. !B3DPrimitiveRasterizerState methodsFor: 'growing' stamp: 'ar 4/13/1999 06:30'!
  13724. growAttrs
  13725.     "Transcript cr; show:'Growing attrAlloc'."
  13726.     attrAlloc _ self grow: attrAlloc.! !
  13727.  
  13728. !B3DPrimitiveRasterizerState methodsFor: 'growing' stamp: 'ar 4/13/1999 06:30'!
  13729. growEdges
  13730.     "Transcript cr; show:'Growing edgeAlloc'."
  13731.     edgeAlloc _ self grow: edgeAlloc.! !
  13732.  
  13733. !B3DPrimitiveRasterizerState methodsFor: 'growing' stamp: 'ar 4/13/1999 06:30'!
  13734. growFaces
  13735.     "Transcript cr; show:'Growing faceAlloc'."
  13736.     faceAlloc _ self grow: faceAlloc.! !
  13737.  
  13738. !B3DPrimitiveRasterizerState methodsFor: 'private' stamp: 'ar 4/10/1999 21:29'!
  13739. primInitializeBuffers
  13740.     <primitive: 'b3dInitializeRasterizerState' module:'Squeak3D'>
  13741.     ^self primitiveFailed! !
  13742.  
  13743. !B3DPrimitiveRasterizerState methodsFor: 'private' stamp: 'ar 4/14/1999 05:13'!
  13744. primTextureSize
  13745.     <primitive:'b3dPrimitiveTextureSize' module:'Squeak3D'>
  13746.     ^self primitiveFailed! !
  13747.  
  13748. I am a shader that uses primitive level support.
  13749. NOTE: Currently, primitive and non-primitive lights cannot be mixed.!
  13750. !B3DPrimitiveShader methodsFor: 'initialize' stamp: 'ar 2/17/1999 04:17'!
  13751. initialize
  13752.     super initialize.
  13753.     primitiveLights _ #().! !
  13754.  
  13755. !B3DPrimitiveShader methodsFor: 'initialize' stamp: 'ar 4/10/1999 22:56'!
  13756. reset
  13757.     super reset.
  13758.     primitiveLights _ #().! !
  13759.  
  13760. !B3DPrimitiveShader methodsFor: 'accessing' stamp: 'ar 2/17/1999 04:14'!
  13761. addLight: aLightSource
  13762.     "NOTE: This does not work if primitive/non-primitive lights are mixed!!"
  13763.     | primLight |
  13764.     self flag: #b3dBug. "See above"
  13765.     primLight _ aLightSource asPrimitiveLight.
  13766.     primLight ifNotNil:[primitiveLights _ primitiveLights copyWith: primLight].
  13767.     ^super addLight: aLightSource! !
  13768.  
  13769. !B3DPrimitiveShader methodsFor: 'accessing' stamp: 'ar 2/17/1999 04:17'!
  13770. removeLight: lightIndex
  13771.     | pLight |
  13772.     super removeLight: lightIndex.
  13773.     self flag: #b3dBug. 
  13774.     "There should be a better way then doing this."
  13775.     primitiveLights _ #().
  13776.     lights do:[:light| 
  13777.         light ifNotNil:[pLight _ light asPrimitiveLight].
  13778.         pLight ifNotNil:[primitiveLights _ primitiveLights copyWith: pLight]].! !
  13779.  
  13780. !B3DPrimitiveShader methodsFor: 'shading' stamp: 'ar 2/17/1999 04:10'!
  13781. primShadeVB: vertexArray count: vtxCount lights: lightArray material: aMaterial vbFlags: vbFlags
  13782.     "Primitive. Shade all the vertices in the vertex buffer using the given array of primitive light sources. Return true on success, false otherwise."
  13783.     <primitive: 'b3dShadeVertexBuffer' module:'Squeak3D'>
  13784.     self flag: #b3dDebug. self primitiveFailed.
  13785.     ^false! !
  13786.  
  13787. !B3DPrimitiveShader methodsFor: 'shading' stamp: 'ar 2/17/1999 04:11'!
  13788. processVertexBuffer: vb
  13789.     "Do the primitive operation"
  13790.     (self primShadeVB: vb vertexArray 
  13791.                 count: vb vertexCount 
  13792.                 lights: primitiveLights 
  13793.                 material: material 
  13794.                 vbFlags: vb flags) ifTrue:[^self].
  13795.     "Run simulation instead"
  13796.     super processVertexBuffer: vb.! !
  13797.  
  13798. !B3DPrimitiveShader class methodsFor: 'accessing' stamp: 'ar 2/17/1999 04:09'!
  13799. version
  13800.     "Return the version of this shader"
  13801.     <primitive:'b3dShaderVersion' module:'Squeak3D'>
  13802.     ^0! !
  13803.  
  13804. !B3DPrimitiveShader class methodsFor: 'testing' stamp: 'ar 2/17/1999 04:08'!
  13805. isAvailable
  13806.     ^self version > 0! !
  13807.  
  13808. I am a vertex transformer that uses some primitive level support.!
  13809. !B3DPrimitiveTransformer methodsFor: 'private-transforming' stamp: 'ar 2/17/1999 04:19'!
  13810. privateTransformMatrix: m1 with: m2 into: m3
  13811.     "Use the primitive operation"
  13812.     <primitive: 'b3dTransformMatrixWithInto' module:'Squeak3D'>
  13813.     ^super privateTransformMatrix: m1 with: m2 into: m3! !
  13814.  
  13815. !B3DPrimitiveTransformer methodsFor: 'private-transforming' stamp: 'ar 2/17/1999 04:20'!
  13816. privateTransformPrimitiveNormal: primitiveVertex byMatrix: aMatrix rescale: scaleNeeded
  13817.     "Use the primitive operation"
  13818.     <primitive: 'b3dTransformPrimitiveNormal' module:'Squeak3D'>
  13819.     ^super privateTransformPrimitiveNormal: primitiveVertex byMatrix: aMatrix rescale: scaleNeeded! !
  13820.  
  13821. !B3DPrimitiveTransformer methodsFor: 'private-transforming' stamp: 'ar 2/17/1999 04:20'!
  13822. privateTransformPrimitiveVertex: primitiveVertex byModelView: aMatrix
  13823.     "Use the primitive operation"
  13824.     <primitive: 'b3dTransformPrimitivePosition' module:'Squeak3D'>
  13825.     ^super privateTransformPrimitiveVertex: primitiveVertex byModelView: aMatrix! !
  13826.  
  13827. !B3DPrimitiveTransformer methodsFor: 'private-transforming' stamp: 'ar 2/17/1999 04:21'!
  13828. privateTransformPrimitiveVertex: primitiveVertex byProjection: aMatrix
  13829.     "Use the primitive operation"
  13830.     <primitive: 'b3dTransformPrimitiveRasterPosition' module:'Squeak3D'>
  13831.     ^super privateTransformPrimitiveVertex: primitiveVertex byProjection: aMatrix! !
  13832.  
  13833. !B3DPrimitiveTransformer methodsFor: 'private-transforming' stamp: 'ar 2/17/1999 04:21'!
  13834. privateTransformVB: vertexArray count: vertexCount modelViewMatrix: modelViewMatrix projectionMatrix: projectionMatrix flags: flags
  13835.     "Use the primitive operation"
  13836.     <primitive: 'b3dTransformVertexBuffer' module:'Squeak3D'>
  13837.     ^super privateTransformVB: vertexArray count: vertexCount modelViewMatrix: modelViewMatrix projectionMatrix: projectionMatrix flags: flags! !
  13838.  
  13839. !B3DPrimitiveTransformer class methodsFor: 'accessing' stamp: 'ar 2/17/1999 04:29'!
  13840. version
  13841.     "Return the version of this transformer"
  13842.     <primitive:'b3dTransformerVersion' module:'Squeak3D'>
  13843.     ^0! !
  13844.  
  13845. !B3DPrimitiveTransformer class methodsFor: 'testing' stamp: 'ar 2/17/1999 04:22'!
  13846. isAvailable
  13847.     ^self version > 0! !
  13848.  
  13849. I represent all per vertex information used in Balloon 3D primitive operations. I store either 32bit floats or integers depending on what is requested.
  13850.  
  13851. C representation:
  13852.  
  13853.     typedef struct B3DPrimitiveVertex {
  13854.         float position[3];
  13855.         float normal[3];
  13856.         float texCoord[2];
  13857.         float rasterPos[4];
  13858.         int pixelValue32;
  13859.         int clipFlags;
  13860.         int windowPos[2];
  13861.     } B3DPrimitiveVertex;!
  13862. !B3DPrimitiveVertex methodsFor: 'accessing' stamp: 'ar 2/5/1999 19:27'!
  13863. b3dColor
  13864.     ^self color asB3DColor! !
  13865.  
  13866. !B3DPrimitiveVertex methodsFor: 'accessing' stamp: 'ar 2/5/1999 19:28'!
  13867. b3dColor: aB3DColor4
  13868.     self color: aB3DColor4 asColor! !
  13869.  
  13870. !B3DPrimitiveVertex methodsFor: 'accessing' stamp: 'ar 2/4/1999 23:53'!
  13871. clipFlags
  13872.     ^self wordAt: 14! !
  13873.  
  13874. !B3DPrimitiveVertex methodsFor: 'accessing' stamp: 'ar 2/4/1999 23:53'!
  13875. clipFlags: aNumber
  13876.     self wordAt: 14 put: aNumber! !
  13877.  
  13878. !B3DPrimitiveVertex methodsFor: 'accessing'!
  13879. color
  13880.     ^self pixelValue32 asColorOfDepth: 32! !
  13881.  
  13882. !B3DPrimitiveVertex methodsFor: 'accessing' stamp: 'ar 2/4/1999 20:21'!
  13883. color: aColor
  13884.     self pixelValue32: (aColor asColor pixelWordForDepth: 32)! !
  13885.  
  13886. !B3DPrimitiveVertex methodsFor: 'accessing' stamp: 'ar 2/5/1999 19:20'!
  13887. floatAt: index
  13888.     <primitive:'primitiveFloatArrayAt'>
  13889.     ^Float fromIEEE32Bit: (self basicAt: index)! !
  13890.  
  13891. !B3DPrimitiveVertex methodsFor: 'accessing' stamp: 'ar 2/5/1999 19:21'!
  13892. floatAt: index put: value
  13893.     <primitive:'primitiveFloatArrayAtPut'>
  13894.     value isFloat 
  13895.         ifTrue:[self basicAt: index put: value asIEEE32BitWord]
  13896.         ifFalse:[self at: index put: value asFloat].
  13897.     ^value! !
  13898.  
  13899. !B3DPrimitiveVertex methodsFor: 'accessing' stamp: 'ar 4/4/1999 00:29'!
  13900. integerAt: index
  13901.     | word |
  13902.     word _ self basicAt: index.
  13903.     word < 16r3FFFFFFF ifTrue:[^word]. "Avoid LargeInteger computations"
  13904.     ^word >= 16r80000000    "Negative?!!"
  13905.         ifTrue:["word - 16r100000000"
  13906.                 (word bitInvert32 + 1) negated]
  13907.         ifFalse:[word]! !
  13908.  
  13909. !B3DPrimitiveVertex methodsFor: 'accessing' stamp: 'ar 4/4/1999 00:29'!
  13910. integerAt: index put: anInteger
  13911.     | word |
  13912.     anInteger < 0
  13913.         ifTrue:["word _ 16r100000000 + anInteger"
  13914.                 word _ (anInteger + 1) negated bitInvert32]
  13915.         ifFalse:[word _ anInteger].
  13916.     self  basicAt: index put: word.
  13917.     ^anInteger! !
  13918.  
  13919. !B3DPrimitiveVertex methodsFor: 'accessing'!
  13920. normal
  13921.     ^B3DVector3 
  13922.         x: (self floatAt: 4) 
  13923.         y: (self floatAt: 5) 
  13924.         z: (self floatAt: 6)! !
  13925.  
  13926. !B3DPrimitiveVertex methodsFor: 'accessing'!
  13927. normal: aVector
  13928.     self floatAt: 4 put: aVector x.
  13929.     self floatAt: 5 put: aVector y.
  13930.     self floatAt: 6 put: aVector z.
  13931. ! !
  13932.  
  13933. !B3DPrimitiveVertex methodsFor: 'accessing'!
  13934. pixelValue32
  13935.     ^self wordAt: 13! !
  13936.  
  13937. !B3DPrimitiveVertex methodsFor: 'accessing'!
  13938. pixelValue32: aNumber
  13939.     self wordAt: 13 put: aNumber! !
  13940.  
  13941. !B3DPrimitiveVertex methodsFor: 'accessing'!
  13942. position
  13943.     ^B3DVector3 
  13944.         x: (self floatAt: 1) 
  13945.         y: (self floatAt: 2) 
  13946.         z: (self floatAt: 3)! !
  13947.  
  13948. !B3DPrimitiveVertex methodsFor: 'accessing'!
  13949. position: aVector
  13950.     self floatAt: 1 put: aVector x.
  13951.     self floatAt: 2 put: aVector y.
  13952.     self floatAt: 3 put: aVector z.
  13953. ! !
  13954.  
  13955. !B3DPrimitiveVertex methodsFor: 'accessing'!
  13956. rasterPos
  13957.     ^B3DVector4
  13958.         x: (self floatAt: 9) 
  13959.         y: (self floatAt: 10) 
  13960.         z: (self floatAt: 11)
  13961.         w: (self floatAt: 12)! !
  13962.  
  13963. !B3DPrimitiveVertex methodsFor: 'accessing'!
  13964. rasterPos: aVector
  13965.     self floatAt: 9 put: aVector x.
  13966.     self floatAt: 10 put: aVector y.
  13967.     self floatAt: 11 put: aVector z.
  13968.     self floatAt: 12 put: aVector w.! !
  13969.  
  13970. !B3DPrimitiveVertex methodsFor: 'accessing'!
  13971. texCoords
  13972.     ^(self floatAt: 7) @ (self floatAt: 8)! !
  13973.  
  13974. !B3DPrimitiveVertex methodsFor: 'accessing' stamp: 'ar 2/5/1999 19:30'!
  13975. texCoords: aVector
  13976.     self floatAt: 7 put: aVector x.
  13977.     self floatAt: 8 put: aVector y.
  13978. ! !
  13979.  
  13980. !B3DPrimitiveVertex methodsFor: 'accessing' stamp: 'ar 4/4/1999 00:21'!
  13981. windowPos
  13982.     ^self windowPosX@self windowPosY! !
  13983.  
  13984. !B3DPrimitiveVertex methodsFor: 'accessing' stamp: 'ar 4/4/1999 00:22'!
  13985. windowPos: aPoint
  13986.     self windowPosX: aPoint x.
  13987.     self windowPosY: aPoint y.! !
  13988.  
  13989. !B3DPrimitiveVertex methodsFor: 'accessing'!
  13990. wordAt: index
  13991.     <primitive: 60>
  13992.     ^self primitiveFailed! !
  13993.  
  13994. !B3DPrimitiveVertex methodsFor: 'accessing'!
  13995. wordAt: index put: value
  13996.     <primitive: 61>
  13997.     ^self primitiveFailed! !
  13998.  
  13999. !B3DPrimitiveVertex methodsFor: 'transform-support' stamp: 'ar 2/8/1999 17:48'!
  14000. normalX
  14001.     ^self floatAt: 4! !
  14002.  
  14003. !B3DPrimitiveVertex methodsFor: 'transform-support' stamp: 'ar 2/8/1999 17:50'!
  14004. normalX: aFloat
  14005.     self floatAt: 4 put: aFloat! !
  14006.  
  14007. !B3DPrimitiveVertex methodsFor: 'transform-support' stamp: 'ar 2/8/1999 17:48'!
  14008. normalY
  14009.     ^self floatAt: 5! !
  14010.  
  14011. !B3DPrimitiveVertex methodsFor: 'transform-support' stamp: 'ar 2/8/1999 17:50'!
  14012. normalY: aFloat
  14013.     self floatAt: 5 put: aFloat! !
  14014.  
  14015. !B3DPrimitiveVertex methodsFor: 'transform-support' stamp: 'ar 2/8/1999 17:48'!
  14016. normalZ
  14017.     ^self floatAt: 6! !
  14018.  
  14019. !B3DPrimitiveVertex methodsFor: 'transform-support' stamp: 'ar 2/8/1999 17:50'!
  14020. normalZ: aFloat
  14021.     self floatAt: 6 put: aFloat! !
  14022.  
  14023. !B3DPrimitiveVertex methodsFor: 'transform-support'!
  14024. positionX
  14025.     ^self floatAt: 1! !
  14026.  
  14027. !B3DPrimitiveVertex methodsFor: 'transform-support'!
  14028. positionX: aNumber
  14029.     self floatAt: 1 put: aNumber! !
  14030.  
  14031. !B3DPrimitiveVertex methodsFor: 'transform-support'!
  14032. positionY
  14033.     ^self floatAt: 2! !
  14034.  
  14035. !B3DPrimitiveVertex methodsFor: 'transform-support'!
  14036. positionY: aNumber
  14037.     self floatAt: 2 put: aNumber! !
  14038.  
  14039. !B3DPrimitiveVertex methodsFor: 'transform-support'!
  14040. positionZ
  14041.     ^self floatAt: 3! !
  14042.  
  14043. !B3DPrimitiveVertex methodsFor: 'transform-support'!
  14044. positionZ: aNumber
  14045.     self floatAt: 3 put: aNumber! !
  14046.  
  14047. !B3DPrimitiveVertex methodsFor: 'transform-support'!
  14048. rasterPosW
  14049.     ^self floatAt: 12! !
  14050.  
  14051. !B3DPrimitiveVertex methodsFor: 'transform-support'!
  14052. rasterPosW: aNumber
  14053.     self floatAt: 12 put: aNumber! !
  14054.  
  14055. !B3DPrimitiveVertex methodsFor: 'transform-support'!
  14056. rasterPosX
  14057.     ^self floatAt: 9! !
  14058.  
  14059. !B3DPrimitiveVertex methodsFor: 'transform-support'!
  14060. rasterPosX: aNumber
  14061.     self floatAt: 9 put: aNumber! !
  14062.  
  14063. !B3DPrimitiveVertex methodsFor: 'transform-support'!
  14064. rasterPosY
  14065.     ^self floatAt: 10! !
  14066.  
  14067. !B3DPrimitiveVertex methodsFor: 'transform-support'!
  14068. rasterPosY: aNumber
  14069.     self floatAt: 10 put: aNumber! !
  14070.  
  14071. !B3DPrimitiveVertex methodsFor: 'transform-support'!
  14072. rasterPosZ
  14073.     ^self floatAt: 11! !
  14074.  
  14075. !B3DPrimitiveVertex methodsFor: 'transform-support'!
  14076. rasterPosZ: aNumber
  14077.     self floatAt: 11 put: aNumber! !
  14078.  
  14079. !B3DPrimitiveVertex methodsFor: 'transform-support' stamp: 'ar 4/4/1999 00:31'!
  14080. windowPosX
  14081.     ^self integerAt: 15! !
  14082.  
  14083. !B3DPrimitiveVertex methodsFor: 'transform-support' stamp: 'ar 4/4/1999 00:31'!
  14084. windowPosX: anInteger
  14085.     self integerAt: 15 put: anInteger! !
  14086.  
  14087. !B3DPrimitiveVertex methodsFor: 'transform-support' stamp: 'ar 4/4/1999 00:31'!
  14088. windowPosY
  14089.     ^self integerAt: 16! !
  14090.  
  14091. !B3DPrimitiveVertex methodsFor: 'transform-support' stamp: 'ar 4/4/1999 00:31'!
  14092. windowPosY: anInteger
  14093.     self integerAt: 16 put: anInteger! !
  14094.  
  14095. !B3DPrimitiveVertex methodsFor: 'private'!
  14096. privateReplaceFrom: start to: stop with: replacement startingAt: repStart 
  14097.     <primitive: 105>
  14098.     start to: stop do:[:i|
  14099.         self basicAt: i put: (replacement basicAt: i - start + repStart).
  14100.     ].! !
  14101.  
  14102. !B3DPrimitiveVertex methodsFor: 'rasterizer-support' stamp: 'ar 4/6/1999 22:27'!
  14103. aValue
  14104.     ^self pixelValue32 bitShift: -24! !
  14105.  
  14106. !B3DPrimitiveVertex methodsFor: 'rasterizer-support' stamp: 'ar 4/6/1999 22:29'!
  14107. alphaValue
  14108.     ^self pixelValue32 bitShift: -24! !
  14109.  
  14110. !B3DPrimitiveVertex methodsFor: 'rasterizer-support' stamp: 'ar 4/6/1999 22:28'!
  14111. bValue
  14112.     ^self pixelValue32 bitAnd: 255! !
  14113.  
  14114. !B3DPrimitiveVertex methodsFor: 'rasterizer-support' stamp: 'ar 4/6/1999 22:29'!
  14115. blueValue
  14116.     ^self pixelValue32 bitAnd: 255! !
  14117.  
  14118. !B3DPrimitiveVertex methodsFor: 'rasterizer-support' stamp: 'ar 4/6/1999 22:28'!
  14119. gValue
  14120.     ^(self pixelValue32 bitShift: -8) bitAnd: 255! !
  14121.  
  14122. !B3DPrimitiveVertex methodsFor: 'rasterizer-support' stamp: 'ar 4/6/1999 22:29'!
  14123. greenValue
  14124.     ^(self pixelValue32 bitShift: -8) bitAnd: 255! !
  14125.  
  14126. !B3DPrimitiveVertex methodsFor: 'rasterizer-support' stamp: 'ar 4/6/1999 22:28'!
  14127. rValue
  14128.     ^(self pixelValue32 bitShift: -16) bitAnd: 255! !
  14129.  
  14130. !B3DPrimitiveVertex methodsFor: 'rasterizer-support' stamp: 'ar 4/6/1999 22:29'!
  14131. redValue
  14132.     ^(self pixelValue32 bitShift: -16) bitAnd: 255! !
  14133.  
  14134. !B3DPrimitiveVertex methodsFor: 'rasterizer-support' stamp: 'ar 4/18/1999 06:26'!
  14135. texCoordS
  14136.     ^self floatAt: 7! !
  14137.  
  14138. !B3DPrimitiveVertex methodsFor: 'rasterizer-support' stamp: 'ar 4/18/1999 06:26'!
  14139. texCoordT
  14140.     ^self floatAt: 8! !
  14141.  
  14142. !B3DPrimitiveVertex methodsFor: 'testing' stamp: 'ar 4/4/1999 00:50'!
  14143. sortsBefore: pVertex
  14144.     "Return true if the receiver should be sorted before the given primitive vertex.
  14145.     Support for rasterizer simulation. Only valid if window position has been computed before."
  14146.     | y0 y1 |
  14147.     y0 _ self windowPosY.
  14148.     y1 _ pVertex windowPosY.
  14149.     y0 = y1 
  14150.         ifTrue:[^self windowPosX <= pVertex windowPosX]
  14151.         ifFalse:[^y0 < y1]! !
  14152.  
  14153. !B3DPrimitiveVertex class methodsFor: 'instance creation' stamp: 'ar 2/14/1999 01:23'!
  14154. new
  14155.     ^self new: PrimVertexSize! !
  14156.  
  14157. I store Balloon 3D primitive vertices in place. I am used to pass data efficiently to the primitive level during high-bandwidth operations.!
  14158. !B3DPrimitiveVertexArray methodsFor: 'accessing' stamp: 'ar 2/14/1999 01:24'!
  14159. at: index
  14160.     "Return the primitive vertex at the given index"
  14161.     | vtx |
  14162.     (index < 1 or:[index > self size]) ifTrue:[^self errorSubscriptBounds: index].
  14163.     vtx _ B3DPrimitiveVertex new.
  14164.     vtx privateReplaceFrom: 1 to: vtx size with: self startingAt: index-1*PrimVertexSize+1.
  14165.     ^vtx! !
  14166.  
  14167. !B3DPrimitiveVertexArray methodsFor: 'accessing' stamp: 'ar 2/14/1999 01:24'!
  14168. at: index put: aB3DPrimitiveVertex
  14169.     "Store the primitive vertex at the given index in the receiver"
  14170.     | idx |
  14171.     (index < 1 or:[index > self size]) ifTrue:[^self errorSubscriptBounds: index].
  14172.     idx _ index-1*PrimVertexSize.
  14173.     self privateReplaceFrom: idx+1 to: idx+PrimVertexSize with: aB3DPrimitiveVertex startingAt: 1.
  14174.     ^aB3DPrimitiveVertex! !
  14175.  
  14176. !B3DPrimitiveVertexArray methodsFor: 'accessing' stamp: 'ar 2/14/1999 01:24'!
  14177. size
  14178.     "Return the number of primitive vertices that can be stored in the receiver"
  14179.     ^self basicSize // PrimVertexSize! !
  14180.  
  14181. !B3DPrimitiveVertexArray methodsFor: 'private'!
  14182. privateReplaceFrom: start to: stop with: replacement startingAt: repStart 
  14183.     <primitive: 105>
  14184.     start to: stop do:[:i|
  14185.         self basicAt: i put: (replacement at: i - start + repStart).
  14186.     ].! !
  14187.  
  14188. !B3DPrimitiveVertexArray methodsFor: 'enumerating' stamp: 'ar 2/4/1999 23:57'!
  14189. upTo: max do: aBlock
  14190.     "Special enumeration message so the client can modify the vertices"
  14191.     | vtx |
  14192.     1 to: max do:[:i|
  14193.         vtx _ self at: i.
  14194.         aBlock value: vtx.
  14195.         self at: i put: vtx].! !
  14196.  
  14197. !B3DPrimitiveVertexArray methodsFor: 'enumerating' stamp: 'ar 2/4/1999 23:59'!
  14198. upTo: max doWithIndex: aBlock
  14199.     "Special enumeration message so the client can modify the vertices"
  14200.     | vtx |
  14201.     1 to: max do:[:i|
  14202.         vtx _ self at: i.
  14203.         aBlock value: vtx value: i.
  14204.         self at: i put: vtx].! !
  14205.  
  14206. !B3DPrimitiveVertexArray class methodsFor: 'instance creation' stamp: 'ar 2/14/1999 01:24'!
  14207. new: n
  14208.     ^super new: (n * PrimVertexSize)! !
  14209.  
  14210. !B3DRasterizerPlugin methodsFor: 'primitives' stamp: 'ar 4/17/1999 20:57'!
  14211. b3dInitPrimitiveObject
  14212.     | vtxSize vtxArray idxSize idxArray primitive primOop primObj primSize textureIndex |
  14213.     self export: true.
  14214.     self inline: false.
  14215.     self var: #vtxArray declareC:'int *vtxArray'.
  14216.     self var: #idxArray declareC:'int *idxArray'.
  14217.     self var: #primObj declareC:'void *primObj'.
  14218.     "Check argument count"
  14219.     interpreterProxy methodArgumentCount = 8
  14220.         ifFalse:[^interpreterProxy primitiveFail].
  14221.  
  14222.     "Fetch the texture index"
  14223.     textureIndex _ interpreterProxy stackIntegerValue: 0.
  14224.     interpreterProxy failed ifTrue:[^nil].
  14225.  
  14226.     "Load the viewport"
  14227.     self loadViewportFrom: 1.
  14228.     interpreterProxy failed ifTrue:[^nil].
  14229.  
  14230.     "Fetch and validate the primitive vertex array"
  14231.     vtxSize _ interpreterProxy stackIntegerValue: 4.
  14232.     vtxArray _ self stackPrimitiveVertexArray: 5 ofSize: vtxSize.
  14233.     vtxArray = nil
  14234.         ifTrue:[^interpreterProxy primitiveFail].
  14235.     "Fetch and validate the primitive index array"
  14236.     idxSize _ interpreterProxy stackIntegerValue: 2.
  14237.     idxArray _ self stackPrimitiveIndexArray: 3 ofSize: idxSize validate: true forVertexSize: vtxSize.
  14238.     idxArray = nil
  14239.         ifTrue:[^interpreterProxy primitiveFail].
  14240.  
  14241.     "Fetch and validate the primitive type"
  14242.     primitive _ interpreterProxy stackIntegerValue: 6.
  14243.     (primitive < 1 or:[primitive > PrimTypeMax]) 
  14244.         ifTrue:[^interpreterProxy primitiveFail].
  14245.  
  14246.     "For now we only support indexed triangles, quads and polys"
  14247.     (primitive = 3 or:[primitive = 5 or:[primitive = 6]]) ifFalse:[^interpreterProxy primitiveFail].
  14248.  
  14249.     "Load the primitive object"
  14250.     primOop _ interpreterProxy stackObjectValue: 7.
  14251.     interpreterProxy failed ifTrue:[^nil].
  14252.     (interpreterProxy isWords: primOop)
  14253.         ifFalse:[^interpreterProxy primitiveFail].
  14254.     primObj _ interpreterProxy firstIndexableField: primOop.
  14255.     primSize _ interpreterProxy byteSizeOf: primOop.
  14256.  
  14257.     "Do the work"
  14258.     primitive = 3 ifTrue:[
  14259.         (self cCode: 'b3dAddPolygonObject((void*) primObj, primSize, B3D_FACE_RGB, textureIndex, (B3DPrimitiveVertex*) vtxArray, vtxSize, &viewport) !!= B3D_NO_ERROR')
  14260.             ifTrue:[^interpreterProxy primitiveFail].
  14261.     ].
  14262.     primitive = 5 ifTrue:[
  14263.         (self cCode:'b3dAddIndexedTriangleObject((void*) primObj, primSize, B3D_FACE_RGB, textureIndex, (B3DPrimitiveVertex*) vtxArray, vtxSize, (B3DInputFace*) idxArray, idxSize / 3, &viewport) !!= B3D_NO_ERROR') 
  14264.             ifTrue:[^interpreterProxy primitiveFail].
  14265.     ].
  14266.     primitive = 6 ifTrue:[
  14267.         (self cCode:'b3dAddIndexedQuadObject((void*) primObj, primSize, B3D_FACE_RGB, textureIndex, (B3DPrimitiveVertex*) vtxArray, vtxSize, (B3DInputQuad*) idxArray, idxSize / 4, &viewport) !!= B3D_NO_ERROR')
  14268.             ifTrue:[^interpreterProxy primitiveFail].
  14269.     ].
  14270.     "Pop args+rcvr; return primitive object"
  14271.     interpreterProxy pop: 9.
  14272.     interpreterProxy push: primOop.! !
  14273.  
  14274. !B3DRasterizerPlugin methodsFor: 'primitives' stamp: 'ar 4/14/1999 05:59'!
  14275. b3dInitializeRasterizerState
  14276.     "Primitive. Initialize the primitive level objects of the given rasterizer."
  14277.     | stateOop objOop objLen obj |
  14278.     self export: true.
  14279.     self inline: false.
  14280.     self var: #obj declareC:'void *obj'.
  14281.  
  14282.     "Check argument count"
  14283.     interpreterProxy methodArgumentCount = 0
  14284.         ifFalse:[^interpreterProxy primitiveFail].
  14285.  
  14286.     stateOop _ interpreterProxy stackObjectValue: 0.
  14287.     interpreterProxy failed ifTrue:[^nil].
  14288.     ((interpreterProxy isPointers: stateOop) and:[(interpreterProxy slotSizeOf: stateOop) >= 7])
  14289.         ifFalse:[^interpreterProxy primitiveFail].
  14290.  
  14291.     objOop _ interpreterProxy fetchPointer: 0 ofObject: stateOop.
  14292.     ((interpreterProxy isIntegerObject: objOop) or:[(interpreterProxy isWords: objOop)  not])
  14293.         ifTrue:[^interpreterProxy primitiveFail].
  14294.     objLen _ interpreterProxy byteSizeOf: objOop.
  14295.     obj _ interpreterProxy firstIndexableField: objOop.
  14296.     (self cCode: 'b3dInitializeFaceAllocator(obj, objLen) !!= B3D_NO_ERROR') 
  14297.         ifTrue:[^interpreterProxy primitiveFail].
  14298.  
  14299.     objOop _ interpreterProxy fetchPointer: 1 ofObject: stateOop.
  14300.     ((interpreterProxy isIntegerObject: objOop) or:[(interpreterProxy isWords: objOop)  not])
  14301.         ifTrue:[^interpreterProxy primitiveFail].
  14302.     objLen _ interpreterProxy byteSizeOf: objOop.
  14303.     obj _ interpreterProxy firstIndexableField: objOop.
  14304.     (self cCode: 'b3dInitializeEdgeAllocator(obj, objLen) !!= B3D_NO_ERROR') 
  14305.         ifTrue:[^interpreterProxy primitiveFail].
  14306.  
  14307.     objOop _ interpreterProxy fetchPointer: 2 ofObject: stateOop.
  14308.     ((interpreterProxy isIntegerObject: objOop) or:[(interpreterProxy isWords: objOop)  not])
  14309.         ifTrue:[^interpreterProxy primitiveFail].
  14310.     objLen _ interpreterProxy byteSizeOf: objOop.
  14311.     obj _ interpreterProxy firstIndexableField: objOop.
  14312.     (self cCode: 'b3dInitializeAttrAllocator(obj, objLen) !!= B3D_NO_ERROR') 
  14313.         ifTrue:[^interpreterProxy primitiveFail].
  14314.  
  14315.     objOop _ interpreterProxy fetchPointer: 3 ofObject: stateOop.
  14316.     ((interpreterProxy isIntegerObject: objOop) or:[(interpreterProxy isWords: objOop)  not])
  14317.         ifTrue:[^interpreterProxy primitiveFail].
  14318.     objLen _ interpreterProxy byteSizeOf: objOop.
  14319.     obj _ interpreterProxy firstIndexableField: objOop.
  14320.     (self cCode: 'b3dInitializeAET(obj, objLen) !!= B3D_NO_ERROR') 
  14321.         ifTrue:[^interpreterProxy primitiveFail].
  14322.  
  14323.     objOop _ interpreterProxy fetchPointer: 4 ofObject: stateOop.
  14324.     ((interpreterProxy isIntegerObject: objOop) or:[(interpreterProxy isWords: objOop)  not])
  14325.         ifTrue:[^interpreterProxy primitiveFail].
  14326.     objLen _ interpreterProxy byteSizeOf: objOop.
  14327.     obj _ interpreterProxy firstIndexableField: objOop.
  14328.     (self cCode: 'b3dInitializeEdgeList(obj, objLen) !!= B3D_NO_ERROR') 
  14329.         ifTrue:[^interpreterProxy primitiveFail].
  14330.  
  14331.     objOop _ interpreterProxy fetchPointer: 5 ofObject: stateOop.
  14332.     ((interpreterProxy isIntegerObject: objOop) or:[(interpreterProxy isWords: objOop)  not])
  14333.         ifTrue:[^interpreterProxy primitiveFail].
  14334.     objLen _ interpreterProxy byteSizeOf: objOop.
  14335.     obj _ interpreterProxy firstIndexableField: objOop.
  14336.     (self cCode: 'b3dInitializeFillList(obj, objLen) !!= B3D_NO_ERROR') 
  14337.         ifTrue:[^interpreterProxy primitiveFail].
  14338.  
  14339.     "Don't pop anything - return the receiver"! !
  14340.  
  14341. !B3DRasterizerPlugin methodsFor: 'primitives' stamp: 'ar 4/14/1999 02:06'!
  14342. b3dPrimitiveObjectSize
  14343.     "Primitive. Return the minimal number of words needed for a primitive object."
  14344.     | objSize |
  14345.     self export: true.
  14346.     self inline: false.
  14347.     objSize _ (self cCode:'sizeof(B3DPrimitiveObject) + sizeof(B3DPrimitiveVertex)') // 4 + 1.
  14348.     interpreterProxy pop: 1.
  14349.     interpreterProxy pushInteger: objSize.! !
  14350.  
  14351. !B3DRasterizerPlugin methodsFor: 'primitives' stamp: 'ar 4/14/1999 05:22'!
  14352. b3dPrimitiveTextureSize
  14353.     "Primitive. Return the minimal number of words needed for a primitive object."
  14354.     | objSize |
  14355.     self export: true.
  14356.     self inline: false.
  14357.     objSize _ (self cCode:'sizeof(B3DTexture)') // 4 + 1.
  14358.     interpreterProxy pop: 1.
  14359.     interpreterProxy pushInteger: objSize.! !
  14360.  
  14361. !B3DRasterizerPlugin methodsFor: 'primitives' stamp: 'ar 4/12/1999 02:19'!
  14362. b3dRasterizerVersion
  14363.     "Primitive. Return the version of the rasterizer."
  14364.     self export: true.
  14365.     self inline: false.
  14366.     interpreterProxy pop: 1.
  14367.     interpreterProxy pushInteger: 1. "Version 1"! !
  14368.  
  14369. !B3DRasterizerPlugin methodsFor: 'primitives' stamp: 'ar 4/14/1999 20:45'!
  14370. b3dStartRasterizer
  14371.     "Primitive. Start the rasterizer."
  14372.     | errCode |
  14373.     self export: true.
  14374.     self inline: false.
  14375.     "Check argument count"
  14376.     interpreterProxy methodArgumentCount = 3
  14377.         ifFalse:[^interpreterProxy primitiveFail].
  14378.  
  14379.     "Load the base rasterizer state"
  14380.     (self loadRasterizerState: 2)
  14381.         ifFalse:[^interpreterProxy primitiveFail].
  14382.     "Load the textures"
  14383.     self loadTexturesFrom: 0.
  14384.     interpreterProxy failed ifTrue:[^nil].
  14385.     "And the objects"
  14386.     self loadObjectsFrom: 1.
  14387.     interpreterProxy failed ifTrue:[^nil].
  14388.     "And go ..."
  14389.     errCode _ self cCode:'b3dMainLoop(&state, B3D_NO_ERROR)'.
  14390.     self storeObjectsInto: 1.
  14391.     interpreterProxy pop: 4.
  14392.     interpreterProxy pushInteger: errCode.! !
  14393.  
  14394. !B3DRasterizerPlugin methodsFor: 'primitives' stamp: 'ar 5/16/2000 20:06'!
  14395. primitiveSetBitBltPlugin
  14396.     "Primitive. Set the BitBlt plugin to use."
  14397.     | pluginName length ptr needReload |
  14398.     self export: true.
  14399.     self var: #ptr declareC:'char *ptr'.
  14400.     pluginName _ interpreterProxy stackValue: 0.
  14401.     "Must be string to work"
  14402.     (interpreterProxy isBytes: pluginName) 
  14403.         ifFalse:[^interpreterProxy primitiveFail].
  14404.     length _ interpreterProxy byteSizeOf: pluginName.
  14405.     length >= 256 
  14406.         ifTrue:[^interpreterProxy primitiveFail].
  14407.     ptr _ interpreterProxy firstIndexableField: pluginName.
  14408.     needReload _ false.
  14409.     0 to: length-1 do:[:i|
  14410.         "Compare and store the plugin to be used"
  14411.         (bbPluginName at: i) = (ptr at: i) ifFalse:[
  14412.             bbPluginName at: i put: (ptr at: i).
  14413.             needReload _ true]].
  14414.     (bbPluginName at: length) = 0 ifFalse:[
  14415.         bbPluginName at: length put: 0.
  14416.         needReload _ true].
  14417.     needReload ifTrue:[
  14418.         self initialiseModule 
  14419.             ifFalse:[^interpreterProxy primitiveFail]].
  14420.     interpreterProxy pop: 1. "Return receiver"! !
  14421.  
  14422. !B3DRasterizerPlugin methodsFor: 'primitive support' stamp: 'ar 4/12/1999 06:02'!
  14423. loadObjectsFrom: stackIndex
  14424.     | arrayOop arraySize objArray objOop objPtr |
  14425.     self var:#objArray declareC:'B3DPrimitiveObject **objArray'.
  14426.     self var:#objPtr declareC:'B3DPrimitiveObject *objPtr'.
  14427.     arrayOop _ interpreterProxy stackObjectValue: stackIndex.
  14428.     interpreterProxy failed ifTrue:[^nil].
  14429.     (interpreterProxy fetchClassOf: arrayOop) == (interpreterProxy classArray)
  14430.         ifFalse:[^interpreterProxy primitiveFail].
  14431.     arraySize _ interpreterProxy slotSizeOf: arrayOop.
  14432.     arraySize > (self cCode:'state.nObjects')
  14433.         ifTrue:[^interpreterProxy primitiveFail].
  14434.     objArray _ self cCode:'state.objects'.
  14435.     0 to: arraySize-1 do:[:i|
  14436.         objOop _ interpreterProxy fetchPointer: i ofObject: arrayOop.
  14437.         ((interpreterProxy isIntegerObject: objOop) or:[(interpreterProxy isWords: objOop) not])
  14438.             ifTrue:[^interpreterProxy primitiveFail].
  14439.         objPtr _ self cCoerce: (interpreterProxy firstIndexableField: objOop) to:'B3DPrimitiveObject*'.
  14440.         (self cCode:'objPtr->magic !!= B3D_PRIMITIVE_OBJECT_MAGIC')
  14441.             ifTrue:[^interpreterProxy primitiveFail].
  14442.         self cCode:'objPtr->__oop__ = objOop'.
  14443.         objArray at: i put: objPtr.
  14444.     ].! !
  14445.  
  14446. !B3DRasterizerPlugin methodsFor: 'primitive support' stamp: 'ar 5/16/2000 17:10'!
  14447. loadRasterizerState: stackIndex
  14448.     "Load the rasterizer state from the given stack index."
  14449.     | stateOop obj objPtr objLen |
  14450.     self var: #objPtr declareC:'void *objPtr'.
  14451.     (copyBitsFn = 0 or:[loadBBFn = 0]) ifTrue:[
  14452.         "We need loadBitBltFrom/copyBits here so try to load it implicitly"
  14453.         self initialiseModule ifFalse:[^false].
  14454.     ].
  14455.     stateOop _ interpreterProxy stackObjectValue: stackIndex.
  14456.     interpreterProxy failed ifTrue:[^false].
  14457.     ((interpreterProxy isPointers: stateOop) and:[(interpreterProxy slotSizeOf: stateOop) >= 10])
  14458.         ifFalse:[^false].
  14459.  
  14460.     obj _ interpreterProxy fetchPointer: 0 ofObject: stateOop.
  14461.     ((interpreterProxy isIntegerObject: obj) or:[(interpreterProxy isWords: obj) not])
  14462.         ifTrue:[^false].
  14463.     objPtr _ interpreterProxy firstIndexableField: obj.
  14464.     self cCode:'state.faceAlloc = objPtr'.
  14465.  
  14466.     obj _ interpreterProxy fetchPointer: 1 ofObject: stateOop.
  14467.     ((interpreterProxy isIntegerObject: obj) or:[(interpreterProxy isWords: obj) not])
  14468.         ifTrue:[^false].
  14469.     objPtr _ interpreterProxy firstIndexableField: obj.
  14470.     self cCode:'state.edgeAlloc = objPtr'.
  14471.  
  14472.     obj _ interpreterProxy fetchPointer: 2 ofObject: stateOop.
  14473.     ((interpreterProxy isIntegerObject: obj) or:[(interpreterProxy isWords: obj) not])
  14474.         ifTrue:[^false].
  14475.     objPtr _ interpreterProxy firstIndexableField: obj.
  14476.     self cCode:'state.attrAlloc = objPtr'.
  14477.  
  14478.     obj _ interpreterProxy fetchPointer: 3 ofObject: stateOop.
  14479.     ((interpreterProxy isIntegerObject: obj) or:[(interpreterProxy isWords: obj) not])
  14480.         ifTrue:[^false].
  14481.     objPtr _ interpreterProxy firstIndexableField: obj.
  14482.     self cCode:'state.aet = objPtr'.
  14483.  
  14484.     obj _ interpreterProxy fetchPointer: 4 ofObject: stateOop.
  14485.     ((interpreterProxy isIntegerObject: obj) or:[(interpreterProxy isWords: obj) not])
  14486.         ifTrue:[^false].
  14487.     objPtr _ interpreterProxy firstIndexableField: obj.
  14488.     self cCode:'state.addedEdges = objPtr'.
  14489.  
  14490.     obj _ interpreterProxy fetchPointer: 5 ofObject: stateOop.
  14491.     ((interpreterProxy isIntegerObject: obj) or:[(interpreterProxy isWords: obj) not])
  14492.         ifTrue:[^false].
  14493.     objPtr _ interpreterProxy firstIndexableField: obj.
  14494.     self cCode:'state.fillList = objPtr'.
  14495.  
  14496.     obj _ interpreterProxy fetchPointer: 6 ofObject: stateOop.
  14497.     obj == interpreterProxy nilObject ifTrue:[
  14498.         self cCode:'state.nObjects = 0'.
  14499.         self cCode:'state.objects = NULL'.
  14500.     ] ifFalse:[
  14501.         ((interpreterProxy isIntegerObject: obj) or:[(interpreterProxy isWords: obj) not])
  14502.             ifTrue:[^false].
  14503.         objLen _ interpreterProxy slotSizeOf: obj.
  14504.         objPtr _ interpreterProxy firstIndexableField: obj.
  14505.         self cCode:'state.objects = (B3DPrimitiveObject **)objPtr'.
  14506.         self cCode:'state.nObjects = objLen'.
  14507.     ].
  14508.  
  14509.     obj _ interpreterProxy fetchPointer: 7 ofObject: stateOop.
  14510.     obj == interpreterProxy nilObject ifTrue:[
  14511.         self cCode:'state.nTextures = 0'.
  14512.         self cCode:'state.textures = NULL'.
  14513.     ] ifFalse:[
  14514.         ((interpreterProxy isIntegerObject: obj) or:[(interpreterProxy isWords: obj) not])
  14515.             ifTrue:[^false].
  14516.         objLen _ interpreterProxy byteSizeOf: obj.
  14517.         objPtr _ interpreterProxy firstIndexableField: obj.
  14518.         self cCode:'state.textures = (B3DTexture *)objPtr'.
  14519.         self cCode:'state.nTextures = objLen / sizeof(B3DTexture)'.
  14520.     ].
  14521.  
  14522.     obj _ interpreterProxy fetchPointer: 8 ofObject: stateOop.
  14523.     obj == interpreterProxy nilObject ifTrue:[
  14524.         self cCode:'state.spanSize = 0'.
  14525.         self cCode:'state.spanBuffer = NULL'.
  14526.     ] ifFalse:[
  14527.         (interpreterProxy fetchClassOf: obj) == (interpreterProxy classBitmap)
  14528.             ifFalse:[^false].
  14529.         objLen _ interpreterProxy slotSizeOf: obj.
  14530.         objPtr _ interpreterProxy firstIndexableField: obj.
  14531.         self cCode:'state.spanBuffer = (unsigned int *)objPtr'.
  14532.         self cCode:'state.spanSize = objLen'.
  14533.     ].
  14534.  
  14535.     obj _ interpreterProxy fetchPointer: 9 ofObject: stateOop.
  14536.     obj == interpreterProxy nilObject ifTrue:[
  14537.         self cCode:'state.spanDrawer = NULL'.
  14538.     ] ifFalse:[
  14539.         (self cCode: '((int (*) (int))loadBBFn)(obj)') ifFalse:[^false].
  14540.         self cCode:'state.spanDrawer = (b3dDrawBufferFunction) copyBitsFn'.
  14541.     ].
  14542.  
  14543.     ^interpreterProxy failed not
  14544. ! !
  14545.  
  14546. !B3DRasterizerPlugin methodsFor: 'primitive support' stamp: 'ar 4/14/1999 05:50'!
  14547. loadTexture: textureOop into: destPtr
  14548.     "Note: This still uses the old-style textures"
  14549.     | form formBits formWidth formHeight formDepth texWrap texInterpolate texEnvMode bitsPtr |
  14550.     self var: #bitsPtr declareC:'void *bitsPtr'.
  14551.     self var: #destPtr declareC:'B3DTexture *destPtr'.
  14552.     "Fetch and validate the form"
  14553.     form _ textureOop.
  14554.     (interpreterProxy isPointers: form) ifFalse:[^false].
  14555.     (interpreterProxy slotSizeOf: form) < 8 ifTrue:[^false].
  14556.     formBits _ interpreterProxy fetchPointer: 0 ofObject: form.
  14557.     formWidth _ interpreterProxy fetchInteger: 1 ofObject: form.
  14558.     formHeight _ interpreterProxy fetchInteger: 2 ofObject: form.
  14559.     formDepth _ interpreterProxy fetchInteger: 3 ofObject: form.
  14560.     texWrap _ interpreterProxy booleanValueOf: 
  14561.         (interpreterProxy fetchPointer: 5 ofObject: form).
  14562.     texInterpolate _ interpreterProxy booleanValueOf: 
  14563.         (interpreterProxy fetchPointer: 6 ofObject: form).
  14564.     texEnvMode _ interpreterProxy fetchInteger: 7 ofObject: form.
  14565.     interpreterProxy failed ifTrue:[^false].
  14566.     (formWidth < 1 or:[formHeight < 1 or:[formDepth ~= 32]]) ifTrue:[^false].
  14567.     (interpreterProxy fetchClassOf: formBits) = interpreterProxy classBitmap ifFalse:[^false].
  14568.     (interpreterProxy byteSizeOf: formBits) = (formWidth * formHeight * 4) ifFalse:[^false].
  14569.     (texEnvMode < 0 or:[texEnvMode > 1]) ifTrue:[^false].
  14570.  
  14571.     "Now fetch the bits"
  14572.     bitsPtr _ interpreterProxy firstIndexableField: formBits.
  14573.     "Set the texture parameters"
  14574.     ^self cCode:'b3dLoadTexture(destPtr, formWidth, formHeight, formDepth, (unsigned int*) bitsPtr, 0, NULL) == B3D_NO_ERROR'.! !
  14575.  
  14576. !B3DRasterizerPlugin methodsFor: 'primitive support' stamp: 'ar 4/14/1999 05:52'!
  14577. loadTexturesFrom: stackIndex
  14578.     | arrayOop destPtr n textureOop |
  14579.     self var: #destPtr declareC:'B3DTexture *destPtr'.
  14580.     arrayOop _ interpreterProxy stackObjectValue: stackIndex.
  14581.     (interpreterProxy fetchClassOf: arrayOop) == interpreterProxy classArray
  14582.         ifFalse:[^interpreterProxy primitiveFail].
  14583.     n _ interpreterProxy slotSizeOf: arrayOop.
  14584.     n _ n min: (self cCode: 'state.nTextures').
  14585.     0 to: n-1 do:[:i|
  14586.         destPtr _ self cCode:'state.textures + i'.
  14587.         textureOop _ interpreterProxy fetchPointer: i ofObject: arrayOop.
  14588.         (self loadTexture: textureOop into: destPtr) 
  14589.             ifFalse:[^interpreterProxy primitiveFail].
  14590.     ].
  14591.     ^0! !
  14592.  
  14593. !B3DRasterizerPlugin methodsFor: 'primitive support' stamp: 'ar 4/10/1999 23:24'!
  14594. loadViewportFrom: stackIndex
  14595.     "Load the viewport from the given stack index"
  14596.     | oop p1 p2 x0 y0 x1 y1 |
  14597.     oop _ interpreterProxy stackObjectValue: stackIndex.
  14598.     interpreterProxy failed ifTrue:[^nil].
  14599.     (interpreterProxy isPointers: oop)
  14600.         ifFalse:[^interpreterProxy primitiveFail].
  14601.     (interpreterProxy slotSizeOf: oop) < 2
  14602.         ifTrue:[^interpreterProxy primitiveFail].
  14603.     p1 _ interpreterProxy fetchPointer: 0 ofObject: oop.
  14604.     p2 _ interpreterProxy fetchPointer: 1 ofObject: oop.
  14605.     (interpreterProxy fetchClassOf: p1) = interpreterProxy classPoint
  14606.         ifFalse:[^interpreterProxy primitiveFail].
  14607.     (interpreterProxy fetchClassOf: p2) = interpreterProxy classPoint
  14608.         ifFalse:[^interpreterProxy primitiveFail].
  14609.     x0 _ interpreterProxy fetchInteger: 0 ofObject: p1.
  14610.     y0 _ interpreterProxy fetchInteger: 1 ofObject: p1.
  14611.     x1 _ (interpreterProxy fetchInteger: 0 ofObject: p2).
  14612.     y1 _ (interpreterProxy fetchInteger: 1 ofObject: p2).
  14613.     interpreterProxy failed ifTrue:[^nil].
  14614.     self cCode:'viewport.x0 = x0'.
  14615.     self cCode:'viewport.y0 = y0'.
  14616.     self cCode:'viewport.x1 = x1'.
  14617.     self cCode:'viewport.y1 = y1'.
  14618.     ^0! !
  14619.  
  14620. !B3DRasterizerPlugin methodsFor: 'primitive support' stamp: 'ar 4/12/1999 06:01'!
  14621. storeObjectsInto: stackIndex
  14622.     | arrayOop arraySize objOop |
  14623.     arrayOop _ interpreterProxy stackObjectValue: stackIndex.
  14624.     arraySize _ self cCode: 'state.nObjects'.
  14625.     0 to: arraySize-1 do:[:i|
  14626.         objOop _ self cCode:'state.objects[i]->__oop__'.
  14627.         interpreterProxy storePointer: i ofObject: arrayOop withValue: objOop.
  14628.     ].! !
  14629.  
  14630. !B3DRasterizerPlugin class methodsFor: 'translation' stamp: 'ar 5/15/2000 23:12'!
  14631. declareCVarsIn: cg
  14632.     cg addHeaderFile:'"b3d.h"'.
  14633.     cg var: #viewport type: #'B3DPrimitiveViewport'.
  14634.     cg var: #state type: #'B3DRasterizerState'! !
  14635.  
  14636. !B3DRasterizerPlugin class methodsFor: 'translation' stamp: 'ar 4/18/1999 08:36'!
  14637. translateSupportCode: cSrc inlining: inlineFlag
  14638.     "Inline the given C support code if inlineFlag is set.
  14639.     Inlining converts any functions of the form:
  14640.         /* INLINE someFunction(args) */
  14641.         void someFunction(declaration args)
  14642.         {
  14643.             ... actual code ...
  14644.         }
  14645.         /* --INLINE-- */
  14646.     into 
  14647.         #define someFunction(args) \
  14648.         /* void someFunction(declaration args) */ \
  14649.         { \
  14650.             ... actual code ... \
  14651.         } \
  14652.         /* --INLINE-- */
  14653.     thus using a hard way of forcing inlining by the C compiler."
  14654.     | in out postfix line |
  14655.     true ifTrue:[^cSrc]. "Disabled until I had time to actually test it ;-)"
  14656.     inlineFlag ifFalse:[^cSrc].
  14657.     in _ ReadStream on: cSrc.
  14658.     out _ WriteStream on: (String new: cSrc size).
  14659.     postfix _ ''.
  14660.     [in atEnd] whileFalse:[
  14661.         line _ in upTo: Character cr.
  14662.         (line includesSubString:' INLINE ') ifTrue:[
  14663.             "New inline start"
  14664.             postfix _ ' \'.
  14665.             line _ line copyFrom: (line findString: 'INLINE')+6 to: line size.
  14666.             line _ line copyFrom: 1 to: (line findString: '*/')-1.
  14667.             out nextPutAll:'#define'; nextPutAll: line; nextPutAll: postfix; cr.
  14668.             "Next line has function declaration -- comment this out"
  14669.             [line _ in upTo: Character cr.
  14670.             line includes: ${] whileFalse:[
  14671.                 out nextPutAll:'/* '; nextPutAll: line; nextPutAll:' */'; nextPutAll: postfix; cr.
  14672.             ].
  14673.             (line first = ${) ifTrue:[
  14674.                 out nextPutAll: line; nextPutAll: postfix; cr.
  14675.             ] ifFalse:[
  14676.                 out nextPutAll: '/* '; 
  14677.                     nextPutAll:(line copyFrom: 1 to: (line findString:'{')-1);
  14678.                     nextPutAll:' */';
  14679.                     nextPutAll:(line copyFrom: (line findString:'{') to: line size);
  14680.                     nextPutAll: postfix;
  14681.                     cr.
  14682.             ].
  14683.         ] ifFalse:[
  14684.             (line includesSubString:'--INLINE--') ifTrue:[postfix _ ''].
  14685.             out nextPutAll: line; nextPutAll: postfix; cr.
  14686.         ].
  14687.     ].
  14688.     ^out contents.
  14689.     "| fs |
  14690.     fs _ FileStream newFileNamed:'b3dr.c'.
  14691.     fs nextPutAll: (B3DRasterizerPlugin translateSupportCode: B3DRasterizerPlugin b3dRemapC inlining: true).
  14692.     fs close."
  14693. ! !
  14694.  
  14695. !B3DRasterizerPlugin class methodsFor: 'translation' stamp: 'ar 5/15/2000 23:10'!
  14696. writeSupportCode: inlineFlag
  14697.     "B3DRasterizerPlugin writeSupportCode: true"
  14698.     "B3DRasterizerPlugin writeSupportCode: false"
  14699.     "Translate all the C support files for the Balloon 3D rasterizer plugin."
  14700.     | src fs |
  14701.     #(
  14702.         (b3dTypesH 'b3dTypes.h')
  14703.         (b3dAllocH 'b3dAlloc.h')
  14704.         (b3dHeaderH 'b3d.h')
  14705.  
  14706.         (b3dInitC 'b3dInit.c')
  14707.         (b3dAllocC 'b3dAlloc.c')
  14708.         (b3dRemapC 'b3dRemap.c')
  14709.         (b3dDrawC 'b3dDraw.c')
  14710.         (b3dMainC 'b3dMain.c')
  14711.     ) do:[:spec|
  14712.         src _ self perform: (spec at: 1).
  14713.         src _ self translateSupportCode: src inlining: inlineFlag.
  14714.         fs _ CrLfFileStream newFileNamed: (spec at: 2).
  14715.         fs nextPutAll: src.
  14716.         fs close.
  14717.     ].! !
  14718.  
  14719. !B3DRasterizerPlugin class methodsFor: 'C source code' stamp: 'ar 4/18/1999 08:30'!
  14720. b3dAllocC
  14721. ^'/****************************************************************************
  14722. *   PROJECT: Balloon 3D Graphics Subsystem for Squeak
  14723. *   FILE:    b3dAlloc.c
  14724. *   CONTENT: Memory allocation for the Balloon 3D rasterizer
  14725. *
  14726. *   AUTHOR:  Andreas Raab (ar)
  14727. *   ADDRESS: Walt Disney Imagineering, Glendale, CA
  14728. *   EMAIL:   andreasr@wdi.disney.com
  14729. *   RCSID:   $Id$
  14730. *
  14731. *   NOTES:
  14732. *
  14733. *
  14734. *****************************************************************************/
  14735. #include <assert.h>
  14736. #include "b3d.h"
  14737.  
  14738. #ifdef DEBUG_ALLOC
  14739. /* DEBUG versions of allocators */
  14740. B3DPrimitiveFace *dbg_b3dAllocFace(B3DFaceAllocList *list)
  14741. {
  14742.     B3DPrimitiveFace *result;
  14743.     if(list->firstFree) {
  14744.         result = list->firstFree;
  14745.         list->firstFree = list->firstFree->nextFree;
  14746.         if(result->flags & B3D_ALLOC_FLAG)
  14747.             b3dAbort("list->firstFree has allocation bit set");
  14748.     } else {
  14749.         if(list->size < list->max) {
  14750.             result = list->data + list->size;
  14751.             list->size++;
  14752.         } else return NULL;
  14753.     }
  14754.     result->nextFree = NULL;
  14755.     result->flags = B3D_ALLOC_FLAG;
  14756.     list->nFree--;
  14757.     return result;
  14758. }
  14759.  
  14760. B3DPrimitiveEdge *dbg_b3dAllocEdge(B3DEdgeAllocList *list)
  14761. {
  14762.     B3DPrimitiveEdge *result;
  14763.     if(list->firstFree) {
  14764.         result = list->firstFree;
  14765.         list->firstFree = list->firstFree->nextFree;
  14766.         if(result->flags & B3D_ALLOC_FLAG)
  14767.             b3dAbort("list->firstFree has allocation bit set");
  14768.     } else {
  14769.         if(list->size < list->max) {
  14770.             result = list->data + list->size;
  14771.             list->size++;
  14772.         } else return NULL;
  14773.     }
  14774.     result->nextFree = NULL;
  14775.     result->flags = B3D_ALLOC_FLAG;
  14776.     list->nFree--;
  14777.     return result;
  14778. }
  14779.  
  14780. void dbg_b3dFreeFace(B3DFaceAllocList *list, B3DPrimitiveFace *face)
  14781. {
  14782.     if(face < list->data || face >= (list->data + list->size))
  14783.         b3dAbort("face to free is not in list");
  14784.     if( !! (face->flags & B3D_ALLOC_FLAG) )
  14785.         b3dAbort("face to free has no allocation flag set");
  14786.     face->flags = 0;
  14787.     face->nextFree = list->firstFree;
  14788.     list->firstFree = face;
  14789.     list->nFree++;
  14790. }
  14791.  
  14792. void dbg_b3dFreeEdge(B3DEdgeAllocList *list, B3DPrimitiveEdge *edge)
  14793. {
  14794.     if(edge < list->data || edge >= (list->data + list->size))
  14795.         b3dAbort("edge to free is not in list");
  14796.     if( !! (edge->flags & B3D_ALLOC_FLAG) )
  14797.         b3dAbort("edge to free has no allocation flag set");
  14798.     edge->flags = 0;
  14799.     edge->nextFree = list->firstFree;
  14800.     list->firstFree = edge;
  14801.     list->nFree++;
  14802. }
  14803.  
  14804. B3DPrimitiveAttribute *dbg_b3dAllocSingleAttr(B3DAttrAllocList *list)
  14805. {
  14806.     B3DPrimitiveAttribute *result;
  14807.     if(list->firstFree) {
  14808.         result = list->firstFree;
  14809.         list->firstFree = list->firstFree->next;
  14810.     } else {
  14811.         if(list->size < list->max) {
  14812.             result = list->data + list->size;
  14813.             list->size++;
  14814.         } else return NULL;
  14815.     }
  14816.     list->nFree--;
  14817.     return result;
  14818. }
  14819.  
  14820. int dbg_b3dAllocAttrib(B3DAttrAllocList *attrList, B3DPrimitiveFace *face)
  14821. {
  14822.     B3DPrimitiveAttribute *firstAttr, *nextAttr;
  14823.     int i, nAttrs = 0;
  14824.  
  14825.     assert(face->attributes == NULL);
  14826.     if(face->flags & B3D_FACE_RGB) nAttrs += 3;
  14827.     if(face->flags & B3D_FACE_ALPHA) nAttrs += 1;
  14828.     if(face->flags & B3D_FACE_STW) nAttrs += 3;
  14829.     if(!!nAttrs) return 1;
  14830.     firstAttr = nextAttr = NULL;
  14831.     for(i=0;i<nAttrs; i++) {
  14832.         nextAttr = dbg_b3dAllocSingleAttr(attrList);
  14833.         if(!!nextAttr) return 0;
  14834.         nextAttr->next = firstAttr;
  14835.         firstAttr = nextAttr;
  14836.     }
  14837.     face->attributes = firstAttr;
  14838.     return 1;
  14839. }
  14840.  
  14841. void dbg_b3dFreeAttrib(B3DAttrAllocList *list, B3DPrimitiveFace *face)
  14842. {
  14843.     B3DPrimitiveAttribute *attr, *nextAttr = face->attributes;
  14844.     while(nextAttr) {
  14845.         attr = nextAttr;
  14846.         nextAttr = attr->next;
  14847.         if(attr < list->data || attr >= (list->data + list->size))
  14848.             b3dAbort("attributes to free are not in list");
  14849.         attr->next = list->firstFree;
  14850.         list->firstFree = attr;
  14851.         list->nFree++;
  14852.     }
  14853. }
  14854.  
  14855.  
  14856. #endif /* DEBUG */
  14857. '! !
  14858.  
  14859. !B3DRasterizerPlugin class methodsFor: 'C source code' stamp: 'ar 4/18/1999 08:35'!
  14860. b3dAllocH
  14861. ^'/****************************************************************************
  14862. *   PROJECT: Balloon 3D Graphics Subsystem for Squeak
  14863. *   FILE:    b3dAlloc.h
  14864. *   CONTENT: Memory allocation for the Balloon 3D rasterizer
  14865. *
  14866. *   AUTHOR:  Andreas Raab (ar)
  14867. *   ADDRESS: Walt Disney Imagineering, Glendale, CA
  14868. *   EMAIL:   andreasr@wdi.disney.com
  14869. *   RCSID:   $Id$
  14870. *
  14871. *   NOTES:
  14872. *
  14873. *
  14874. *****************************************************************************/
  14875. #ifndef B3D_ALLOC_H
  14876. #define B3D_ALLOC_H
  14877.  
  14878. #include "b3dTypes.h"
  14879.  
  14880. /************************ Allocator definitions ************************/
  14881. #define B3D_EDGE_ALLOC_MAGIC 0x45443341
  14882. typedef struct B3DEdgeAllocList {
  14883.     int magic;
  14884.     void *This;
  14885.     int max; /* Note: size is ALWAYS less than max */
  14886.     int size;
  14887.      int nFree;
  14888.     B3DPrimitiveEdge *firstFree; /* pointer to the first free edge (< max) */
  14889.     B3DPrimitiveEdge data[1];
  14890. } B3DEdgeAllocList;
  14891.  
  14892. #define B3D_FACE_ALLOC_MAGIC 0x46443341
  14893. typedef struct B3DFaceAllocList {
  14894.     int magic;
  14895.     void *This;
  14896.     int max; /* Note: size is ALWAYS less than max */
  14897.     int size;
  14898.     int nFree;
  14899.     B3DPrimitiveFace *firstFree; /* pointer to the first free face (< max) */
  14900.     B3DPrimitiveFace data[1];
  14901. } B3DFaceAllocList;
  14902.  
  14903. #define B3D_ATTR_ALLOC_MAGIC  0x41443341
  14904. typedef struct B3DAttrAllocList {
  14905.     int magic;
  14906.     void *This;
  14907.     int max; /* Note: size is ALWAYS less than max */
  14908.     int size;
  14909.     int nFree;
  14910.     B3DPrimitiveAttribute *firstFree; /* pointer to the first free attribute (< max) */
  14911.     B3DPrimitiveAttribute data[1];
  14912. } B3DAttrAllocList;
  14913.  
  14914. /* The mapping from face flags to the number of attributes needed */
  14915. extern int B3D_ATTRIBUTE_SIZES[B3D_MAX_ATTRIBUTES];
  14916. #define B3D_FACE_ATTRIB_SIZE(face) (B3D_ATTRIBUTE_SIZES[(face->flags >> B3D_ATTR_SHIFT) & B3D_ATTR_MASK])
  14917.  
  14918. #ifdef DEBUG_ALLOC
  14919.  
  14920. B3DPrimitiveFace *dbg_b3dAllocFace(B3DFaceAllocList *list);
  14921. B3DPrimitiveEdge *dbg_b3dAllocEdge(B3DEdgeAllocList *list);
  14922. int dbg_b3dAllocAttrib(B3DAttrAllocList *attrList, B3DPrimitiveFace *face);
  14923. void dbg_b3dFreeFace(B3DFaceAllocList *list, B3DPrimitiveFace *face);
  14924. void dbg_b3dFreeEdge(B3DEdgeAllocList *list, B3DPrimitiveEdge *edge);
  14925. void dbg_b3dFreeAttrib(B3DAttrAllocList *list, B3DPrimitiveFace *face);
  14926.  
  14927. #define b3dAllocFace(list, face) face = dbg_b3dAllocFace(list);
  14928. #define b3dAllocEdge(list, edge) edge = dbg_b3dAllocEdge(list);
  14929. #define b3dAllocAttrib(attrList, face, result) result = dbg_b3dAllocAttrib(attrList, face);
  14930. #define b3dFreeFace(list, face) dbg_b3dFreeFace(list, face);
  14931. #define b3dFreeEdge(list, edge) dbg_b3dFreeEdge(list, edge);
  14932. #define b3dFreeAttrib(list, face) dbg_b3dFreeAttrib(list, face);
  14933.  
  14934. #else /* RELEASE */
  14935.  
  14936. #define b3dAlloc(list,object) \
  14937. {\
  14938.     if(list->firstFree) { \
  14939.         object = list->firstFree; \
  14940.         list->firstFree = object->nextFree; \
  14941.         object->flags = B3D_ALLOC_FLAG; \
  14942.         list->nFree--;\
  14943.     } else { \
  14944.         if(list->size < list->max) { \
  14945.             object = list->data + list->size; \
  14946.             list->size++;\
  14947.             object->flags = B3D_ALLOC_FLAG;\
  14948.             list->nFree--;\
  14949.         } else object = NULL;\
  14950.     }\
  14951. }
  14952.  
  14953. #define b3dFree(list, object) \
  14954. {\
  14955.     object->flags = 0;\
  14956.     object->nextFree = list->firstFree; \
  14957.     list->firstFree = object;\
  14958.     list->nFree++;\
  14959. }
  14960.  
  14961. #define b3dAllocFace(list, face) b3dAlloc(list,face)
  14962. #define b3dAllocEdge(list, edge) b3dAlloc(list, edge)
  14963. #define b3dFreeFace(list, face) b3dFree(list, face)
  14964. #define b3dFreeEdge(list, edge) b3dFree(list, edge)
  14965.  
  14966. #define b3dAllocSingleAttr(list,object) \
  14967. {\
  14968.     if(list->firstFree) { \
  14969.         object = list->firstFree; \
  14970.         list->firstFree = object->next; \
  14971.         list->nFree--;\
  14972.     } else { \
  14973.         if(list->size < list->max) { \
  14974.             object = list->data + list->size; \
  14975.             list->size++;\
  14976.             list->nFree--;\
  14977.         } else object = NULL;\
  14978.     }\
  14979. }
  14980.  
  14981. #define b3dAllocAttrib(attrList,face, result) \
  14982. {\
  14983.     B3DPrimitiveAttribute *firstAttr, *nextAttr;\
  14984.     int nAttrs = 0;\
  14985. \
  14986.     if(face->flags & B3D_FACE_RGB) nAttrs += 3;\
  14987.     if(face->flags & B3D_FACE_ALPHA) nAttrs += 1;\
  14988.     if(face->flags & B3D_FACE_STW) nAttrs += 3;\
  14989.     firstAttr = nextAttr = NULL;\
  14990.     while(nAttrs--) {\
  14991.         b3dAllocSingleAttr(attrList, nextAttr);\
  14992.         if(!!nextAttr) break;\
  14993.         nextAttr->next = firstAttr;\
  14994.         firstAttr = nextAttr;\
  14995.     };\
  14996.     face->attributes = firstAttr;\
  14997.     result = nextAttr !!= NULL;\
  14998. }
  14999.  
  15000.  
  15001. #define b3dFreeAttrib(list, face) \
  15002. {\
  15003.     B3DPrimitiveAttribute *attr, *nextAttr = face->attributes;\
  15004.     while(nextAttr) {\
  15005.         attr = nextAttr;\
  15006.         nextAttr = attr->next;\
  15007.         attr->next = list->firstFree;\
  15008.         list->firstFree = attr;\
  15009.         list->nFree++;\
  15010.     }\
  15011. }
  15012.  
  15013. #endif
  15014.  
  15015. #endif /* ifndef B3D_ALLOC_H */
  15016. '! !
  15017.  
  15018. !B3DRasterizerPlugin class methodsFor: 'C source code' stamp: 'ar 4/21/1999 01:58'!
  15019. b3dDrawC
  15020. ^'/****************************************************************************
  15021. *   PROJECT: Balloon 3D Graphics Subsystem for Squeak
  15022. *   FILE:    b3dDraw.c
  15023. *   CONTENT: Pixel drawing functions for the B3D rasterizer
  15024. *
  15025. *   AUTHOR:  Andreas Raab (ar)
  15026. *   ADDRESS: Walt Disney Imagineering, Glendale, CA
  15027. *   EMAIL:   andreasr@wdi.disney.com
  15028. *   RCSID:   $Id$
  15029. *
  15030. *   NOTES:  LOTS of stuff missing here...
  15031. *
  15032. *    - A note on RGBA interpolation:
  15033. *    For low polygon models it makes sense to compute both, the left and
  15034. *    the right attribute value if there might be any overflow at all.
  15035. *    Since we''re usually drawing many pixels in a row we can clamp the
  15036. *    left and right value and thus be safe during the interpolation stage.
  15037. *
  15038. *****************************************************************************/
  15039. #include "b3d.h"
  15040.  
  15041. #define rasterPosX rasterPos[0]
  15042. #define rasterPosY rasterPos[1]
  15043.  
  15044. #define redValue   color[RED_INDEX]
  15045. #define greenValue color[GREEN_INDEX]
  15046. #define blueValue  color[BLUE_INDEX]
  15047. #define alphaValue color[ALPHA_INDEX]
  15048.  
  15049. /* The following defines the maximum number of pixels 
  15050.    we treat in one loop. This value should be carefully
  15051.    chosen: Setting it high will increase speed for larger
  15052.    polygons but reduce speed for smaller ones. Setting
  15053.    it low will do the opposite. Also, since I''m assuming
  15054.    a smart compiler, the code size will probably increase
  15055.    with this number (if loops are unrolled by the compiler).
  15056.  
  15057.    The current value of 5 should be a good median (32 pixels
  15058.    are processed at most and we''ll have the overhead of 5
  15059.    tests for a one-pixel polygon).
  15060. */
  15061. #define MAX_PIXEL_SHIFT 5
  15062.  
  15063.  
  15064. /* USE_MULTBL: Replace up a couple of multiplications by table lookups.
  15065.     On PowerPC, the lookup seems to be slightly slower.
  15066.     On Intel, the lookup is way faster.
  15067. */
  15068. #ifndef USE_MULTBL
  15069. # ifdef __POWERPC__
  15070. #  define USE_MULTBL 0
  15071. # else
  15072. #  define USE_MULTBL 1
  15073. # endif
  15074. #endif
  15075.  
  15076. /* Clamp the given value */
  15077. #define CLAMP(value, min, max)\
  15078.     if((value) < (min)) (value) = (min); \
  15079.     else if((value) > (max)) (value) = (max);
  15080.  
  15081. /* Clamp a set of fixed point RGB values */
  15082. #define CLAMP_RGB(r,g,b) \
  15083.     CLAMP(r,B3D_FixedHalf, (255 << B3D_IntToFixedShift) + B3D_FixedHalf)\
  15084.     CLAMP(g,B3D_FixedHalf, (255 << B3D_IntToFixedShift) + B3D_FixedHalf)\
  15085.     CLAMP(b,B3D_FixedHalf, (255 << B3D_IntToFixedShift) + B3D_FixedHalf)
  15086.  
  15087.  
  15088. #ifdef DEBUG_ATTR
  15089. double attrValueAt(B3DPrimitiveFace *face, B3DPrimitiveAttribute *attr, double xValue, double yValue)
  15090. {
  15091.     return 
  15092.         (attr->value +
  15093.             ((xValue - face->v0->rasterPosX) * attr->dvdx) +
  15094.             ((yValue - face->v0->rasterPosY) * attr->dvdy));
  15095. }
  15096. #else
  15097. #define attrValueAt(face,attr,xValue,yValue) \
  15098.         ((attr)->value + \
  15099.             (((double)(xValue) - (face)->v0->rasterPosX) * (attr)->dvdx) + \
  15100.             (((double)(yValue) - (face)->v0->rasterPosY) * (attr)->dvdy))
  15101. #endif
  15102.  
  15103.  
  15104. #define SETUP_RGB \
  15105.     rValue = (int)(attrValueAt(face, attr, floatX, floatY) * B3D_FloatToFixed); \
  15106.     deltaR = (int) (attr->dvdx * B3D_FloatToFixed);  \
  15107.     attr = attr->next; \
  15108.     gValue = (int)(attrValueAt(face, attr, floatX, floatY) * B3D_FloatToFixed);\
  15109.     deltaG = (int) (attr->dvdx * B3D_FloatToFixed); \
  15110.     attr = attr->next; \
  15111.     bValue = (int)(attrValueAt(face, attr, floatX, floatY) * B3D_FloatToFixed); \
  15112.     deltaB = (int) (attr->dvdx * B3D_FloatToFixed); \
  15113.     attr = attr->next;\
  15114.     CLAMP_RGB(rValue, gValue, bValue);
  15115.  
  15116. #define SETUP_STW \
  15117.     wValue = attrValueAt(face, attr, floatX, floatY); \
  15118.     wDelta = attr->dvdx; \
  15119.     attr = attr->next; \
  15120.     sValue = attrValueAt(face, attr, floatX, floatY); \
  15121.     sDelta = attr->dvdx; \
  15122.     attr = attr->next; \
  15123.     tValue = attrValueAt(face, attr, floatX, floatY); \
  15124.     tDelta = attr->dvdx; \
  15125.     attr = attr->next;
  15126.  
  15127. #define STEP_STW \
  15128.     sValue += sDelta;\
  15129.     tValue += tDelta;\
  15130.     wValue += wDelta;
  15131.  
  15132.  
  15133. /* Load the four neighbouring texels into tex00, tex01, tex10, and tex11 */
  15134. #define LOAD_4_RGB_TEXEL_32(fixedS, fixedT, texture) \
  15135. {\
  15136.     int sIndex, tIndex;\
  15137. \
  15138.     if(texture->sMask) {\
  15139.         sIndex = (fixedS >> B3D_FixedToIntShift) & texture->sMask;\
  15140.     } else {\
  15141.         sIndex = (fixedS >> B3D_FixedToIntShift) % texture->width;\
  15142.     }\
  15143.     if(texture->tMask) {\
  15144.         tIndex = (fixedT >> B3D_FixedToIntShift) & texture->tMask;\
  15145.     } else {\
  15146.         tIndex = (fixedT >> B3D_FixedToIntShift) % texture->height;\
  15147.     }\
  15148.     /* Load the 4 texels, wrapping if necessary */\
  15149.     tex00 = (struct b3dPixelColor *) texture->data + (tIndex * texture->width) + sIndex;\
  15150.     tex01 = tex00 + 1;\
  15151.     tex10 = tex00 + texture->width;\
  15152.     tex11 = tex10 + 1;\
  15153.     if(sIndex+1 == texture->width) {\
  15154.         tex01 -= texture->width;\
  15155.         tex11 -= texture->width;\
  15156.     }\
  15157.     if(tIndex+1 == texture->height) {\
  15158.         int tsize = texture->height * texture->width;\
  15159.         tex10 -= tsize;\
  15160.         tex11 -= tsize;\
  15161.     }\
  15162. }
  15163.  
  15164.  
  15165. #if USE_MULTBL /* Use a 16x256 table for lookups */
  15166.  
  15167. unsigned short MULTBL[17][256];
  15168.  
  15169. static int multblInit = 0;
  15170.  
  15171. static void MULTBL_Init(void)
  15172. {
  15173.     int i,j;
  15174.     for(i=0;i<17;i++)
  15175.         for(j=0; j<256; j++)
  15176.             MULTBL[i][j] = (i*j) >> 4;
  15177.     multblInit = 1;
  15178. }
  15179.  
  15180. #define INIT_MULTBL { if (!!multblInit) MULTBL_Init(); }
  15181.  
  15182. #define DO_RGB_INTERPOLATION(sf, si, tf, ti) \
  15183.     tr = (MULTBL[ti][(MULTBL[si][tex00->redValue] + MULTBL[sf][tex01->redValue])] + \
  15184.             MULTBL[tf][(MULTBL[si][tex10->redValue] + MULTBL[sf][tex11->redValue])]);\
  15185.     tg = (MULTBL[ti][(MULTBL[si][tex00->greenValue] + MULTBL[sf][tex01->greenValue])] + \
  15186.             MULTBL[tf][(MULTBL[si][tex10->greenValue] + MULTBL[sf][tex11->greenValue])]);\
  15187.     tb = (MULTBL[ti][(MULTBL[si][tex00->blueValue] + MULTBL[sf][tex01->blueValue])] + \
  15188.             MULTBL[tf][(MULTBL[si][tex10->blueValue] + MULTBL[sf][tex11->blueValue])]);
  15189.  
  15190. #define DO_RGBA_INTERPOLATION(sf, si, tf, ti)\
  15191.     tr = (MULTBL[ti][(MULTBL[si][tex00->redValue] + MULTBL[sf][tex01->redValue])] + \
  15192.             MULTBL[tf][(MULTBL[si][tex10->redValue] + MULTBL[sf][tex11->redValue])]);\
  15193.     tg = (MULTBL[ti][(MULTBL[si][tex00->greenValue] + MULTBL[sf][tex01->greenValue])] + \
  15194.             MULTBL[tf][(MULTBL[si][tex10->greenValue] + MULTBL[sf][tex11->greenValue])]);\
  15195.     tb = (MULTBL[ti][(MULTBL[si][tex00->blueValue] + MULTBL[sf][tex01->blueValue])] + \
  15196.             MULTBL[tf][(MULTBL[si][tex10->blueValue] + MULTBL[sf][tex11->blueValue])]); \
  15197.     ta = (MULTBL[ti][(MULTBL[si][tex00->alphaValue] + MULTBL[sf][tex01->alphaValue])] + \
  15198.             MULTBL[tf][(MULTBL[si][tex10->alphaValue] + MULTBL[sf][tex11->alphaValue])]);
  15199.  
  15200. #else
  15201.  
  15202. #define INIT_MULTBL
  15203.  
  15204. #define DO_RGB_INTERPOLATION(sf, si, tf, ti) \
  15205.     tr = (ti * (si * tex00->redValue + sf * tex01->redValue) +\
  15206.             tf * (si * tex10->redValue + sf * tex11->redValue)) >> 8;\
  15207.     tg = (ti * (si * tex00->greenValue + sf * tex01->greenValue) +\
  15208.             tf * (si * tex10->greenValue + sf * tex11->greenValue)) >> 8;\
  15209.     tb = (ti * (si * tex00->blueValue + sf * tex01->blueValue) +\
  15210.             tf * (si * tex10->blueValue + sf * tex11->blueValue)) >> 8;\
  15211.  
  15212. #define DO_RGBA_INTERPOLATION(sf, si, tf, ti) \
  15213.     tr = (ti * (si * tex00->redValue + sf * tex01->redValue) +\
  15214.             tf * (si * tex10->redValue + sf * tex11->redValue)) >> 8;\
  15215.     tg = (ti * (si * tex00->greenValue + sf * tex01->greenValue) +\
  15216.             tf * (si * tex10->greenValue + sf * tex11->greenValue)) >> 8;\
  15217.     tb = (ti * (si * tex00->blueValue + sf * tex01->blueValue) +\
  15218.             tf * (si * tex10->blueValue + sf * tex11->blueValue)) >> 8;\
  15219.     ta = (ti * (si * tex00->alphaValue + sf * tex01->alphaValue) +\
  15220.             tf * (si * tex10->alphaValue + sf * tex11->alphaValue)) >> 8;
  15221.  
  15222. #endif /* No MULTBL */
  15223.  
  15224. #define INTERPOLATE_RGB_TEXEL(fixedS, fixedT)\
  15225. {    int sf, si, tf, ti;\
  15226.     sf = (fixedS >> (B3D_FixedToIntShift - 4)) & 15; si = 16 - sf;\
  15227.     tf = (fixedT >> (B3D_FixedToIntShift - 4)) & 15; ti = 16 - tf;\
  15228.     DO_RGB_INTERPOLATION(sf, si, tf, ti)\
  15229. }
  15230.  
  15231. void b3dNoDraw     (int leftX, int rightX, int yValue, B3DPrimitiveFace *face);
  15232. void b3dDrawRGB    (int leftX, int rightX, int yValue, B3DPrimitiveFace *face);
  15233. void b3dDrawRGBA   (int leftX, int rightX, int yValue, B3DPrimitiveFace *face);
  15234. void b3dDrawSTW    (int leftX, int rightX, int yValue, B3DPrimitiveFace *face);
  15235. void b3dDrawSTWA   (int leftX, int rightX, int yValue, B3DPrimitiveFace *face);
  15236. void b3dDrawSTWRGB (int leftX, int rightX, int yValue, B3DPrimitiveFace *face);
  15237. void b3dDrawSTWARGB(int leftX, int rightX, int yValue, B3DPrimitiveFace *face);
  15238.  
  15239. b3dPixelDrawer B3D_FILL_FUNCTIONS[B3D_MAX_ATTRIBUTES] = {
  15240.     b3dNoDraw,      /* No attributes */
  15241.     b3dDrawRGB,     /* B3D_FACE_RGB */
  15242.     b3dNoDraw,      /* B3D_FACE_ALPHA -- IGNORED!!!!!! */
  15243.     b3dDrawRGBA,    /* B3D_FACE_RGB | B3D_FACE_ALPHA */
  15244.     b3dDrawSTW,     /* B3D_FACE_STW */
  15245.     b3dDrawSTWRGB,  /* B3D_FACE_STW | B3D_FACE_RGB */
  15246.     b3dDrawSTWA,    /* B3D_FACE_STW | B3D_FACE_ALPHA */
  15247.     b3dDrawSTWARGB  /* B3D_FACE_STW | B3D_FACE_RGB | B3D_FACE_ALPHA */
  15248. };
  15249.  
  15250. void b3dNoDraw(int leftX, int rightX, int yValue, B3DPrimitiveFace *face)
  15251. {
  15252.     if(b3dDebug)
  15253.         b3dAbort("b3dNoDraw called!!");
  15254. }
  15255.  
  15256. void b3dDrawRGBFlat(int leftX, int rightX, int yValue, B3DPrimitiveFace *face)
  15257. {
  15258.     struct b3dPixelColor { B3DPrimitiveColor color; } pv, *bits;
  15259.     int rValue, gValue, bValue;
  15260.     int deltaR, deltaG, deltaB;
  15261.  
  15262.  
  15263.     {
  15264.         B3DPrimitiveAttribute *attr = face->attributes;
  15265.         /* Ughh ... I''m having a sampling problem somewhere.
  15266.            In theory, the faces should be sampled *exactly* at integer
  15267.            values (the necessary offset should be done before) so that
  15268.            we always sample inside the triangle. For some reason that
  15269.            doesn''t quite work yet and that''s why here is the strange
  15270.            0.5 offset and the awful lot of tests. At some time I''ll
  15271.            review this but for now I have more important things to do.
  15272.         */
  15273.         double floatX = leftX;
  15274.         double floatY = yValue+0.5;
  15275.  
  15276.         if(b3dDebug)
  15277.             if(!!attr) b3dAbort("face has no RGB attributes");
  15278.  
  15279.         SETUP_RGB;
  15280.     }
  15281.  
  15282.     bits = (struct b3dPixelColor *) currentState->spanBuffer;
  15283.     pv.redValue   = (unsigned char) (rValue >> B3D_FixedToIntShift);
  15284.     pv.greenValue = (unsigned char) (gValue >> B3D_FixedToIntShift);
  15285.     pv.blueValue  = (unsigned char) (bValue >> B3D_FixedToIntShift);
  15286.     pv.alphaValue = 255;
  15287.  
  15288.     while(leftX <= rightX) {
  15289.         bits[leftX++] = pv;
  15290.     }
  15291. }
  15292.  
  15293. void b3dDrawRGB(int leftX, int rightX, int yValue, B3DPrimitiveFace *face)
  15294. {
  15295.     struct b3dPixelColor { B3DPrimitiveColor color; } pv, *bits;
  15296.     int rValue, gValue, bValue;
  15297.     int deltaR, deltaG, deltaB;
  15298.     int deltaX, pixelShift;
  15299.  
  15300.     {
  15301.         B3DPrimitiveAttribute *attr = face->attributes;
  15302.         /* Ughh ... I''m having a sampling problem somewhere.
  15303.            In theory, the faces should be sampled *exactly* at integer
  15304.            values (the necessary offset should be done before) so that
  15305.            we always sample inside the triangle. For some reason that
  15306.            doesn''t quite work yet and that''s why here is the strange
  15307.            0.5 offset and the awful lot of tests. At some time I''ll
  15308.            review this but for now I have more important things to do.
  15309.         */
  15310.         double floatX = leftX;
  15311.         double floatY = yValue+0.5;
  15312.  
  15313.         if(b3dDebug)
  15314.             if(!!attr) b3dAbort("face has no RGB attributes");
  15315.  
  15316.         SETUP_RGB;
  15317.     }
  15318.  
  15319.     bits = (struct b3dPixelColor *) currentState->spanBuffer;
  15320.     pv.alphaValue = 255;
  15321.  
  15322.     /*    Reduce the overhead of clamping by precomputing 
  15323.         the deltas for each power of two step. A good question here
  15324.         is whether or not it is a good idea to do 2 pixels by this... */
  15325.     deltaX = rightX - leftX + 1;
  15326.  
  15327.     /* Now do all the powers of two except the last one pixel */
  15328.     /* Note: A smart compiler (== gcc) should unroll the following loop */
  15329.     for(pixelShift= MAX_PIXEL_SHIFT; pixelShift> 0; pixelShift--) {
  15330.         int nPixels = 1 << pixelShift;
  15331.         /* Note: The ''if'' here is possible since 
  15332.            we have dealt with huge polys above */
  15333.         while(deltaX >= nPixels) {    
  15334.             {    /* Compute right most values of color interpolation */
  15335.                 int maxR = rValue + (deltaR << pixelShift);
  15336.                 int maxG = gValue + (deltaG << pixelShift);
  15337.                 int maxB = bValue + (deltaB << pixelShift);
  15338.                 /* Clamp those guys */
  15339.                 CLAMP_RGB(maxR, maxG, maxB);
  15340.                 /* And compute the actual delta */
  15341.                 deltaR = (maxR - rValue) >> pixelShift;
  15342.                 deltaG = (maxG - gValue) >> pixelShift;
  15343.                 deltaB = (maxB - bValue) >> pixelShift;
  15344.             }
  15345.             /* Do the inner loop */
  15346.             {    int n = nPixels;
  15347.                 while(n--) {
  15348.                     pv.redValue   = (unsigned char) (rValue >> B3D_FixedToIntShift);
  15349.                     pv.greenValue = (unsigned char) (gValue >> B3D_FixedToIntShift);
  15350.                     pv.blueValue  = (unsigned char) (bValue >> B3D_FixedToIntShift);
  15351.                     bits[leftX++] = pv;
  15352.                     rValue += deltaR;
  15353.                     gValue += deltaG;
  15354.                     bValue += deltaB;
  15355.                 }
  15356.             }
  15357.             /* Finally, adjust the number of pixels left */
  15358.             deltaX -= nPixels;
  15359.         }
  15360.     }
  15361.     /* The last pixel is done separately */
  15362.     if(deltaX) {
  15363.         pv.redValue   = (unsigned char) (rValue >> B3D_FixedToIntShift);
  15364.         pv.greenValue = (unsigned char) (gValue >> B3D_FixedToIntShift);
  15365.         pv.blueValue  = (unsigned char) (bValue >> B3D_FixedToIntShift);
  15366.         bits[leftX++] = pv;
  15367.     }
  15368. }
  15369.  
  15370. void b3dDrawSTWRGB(int leftX, int rightX, int yValue, B3DPrimitiveFace *face)
  15371. {
  15372.     struct b3dPixelColor { B3DPrimitiveColor color; } pv, *bits, *tex00, *tex10, *tex01, *tex11;
  15373.     double sValue, tValue, wValue, sDelta, tDelta, wDelta, oneOverW;
  15374.     int rValue, gValue, bValue;
  15375.     int deltaR, deltaG, deltaB;
  15376.     int tr, tg, tb, ta;
  15377.     int fixedLeftS, fixedRightS, fixedLeftT, fixedRightT, fixedDeltaS, fixedDeltaT;
  15378.     int deltaX, pixelShift;
  15379.  
  15380.     B3DTexture *texture = face->texture;
  15381.  
  15382.     INIT_MULTBL;
  15383.  
  15384.     if(!!texture || 0) {
  15385.         /* If no texture simply draw RGB */
  15386.         b3dDrawRGB(leftX, rightX, yValue, face);
  15387.         return;
  15388.     }
  15389.     if(texture->depth < 16 && (texture->cmSize < (1 << texture->depth)))
  15390.         return; /* Colormap not installed */
  15391.  
  15392.     {
  15393.         B3DPrimitiveAttribute *attr = face->attributes;
  15394.         /* See above */
  15395.         double floatX = leftX;
  15396.         double floatY = yValue+0.5;
  15397.  
  15398.         if(b3dDebug)
  15399.             if(!!attr) b3dAbort("face has no RGB attributes");
  15400.  
  15401.         SETUP_RGB;
  15402.         SETUP_STW;
  15403.     }
  15404.  
  15405.     tr = tg = tb = ta = 255;
  15406.  
  15407.     bits = (struct b3dPixelColor *) currentState->spanBuffer;
  15408.     pv.alphaValue = 255;
  15409.  
  15410.     /*    VERY Experimental: Reduce the overhead of clamping
  15411.         as well as division by W by precomputing the deltas 
  15412.         for each power of two step */
  15413.     deltaX = rightX - leftX + 1;
  15414.     if(wValue) oneOverW = 1.0 / wValue;
  15415.     else oneOverW = 0.0;
  15416.     fixedLeftS = (int) (sValue * oneOverW * (texture->width << B3D_IntToFixedShift));
  15417.     fixedLeftT = (int) (tValue * oneOverW * (texture->height << B3D_IntToFixedShift));
  15418.  
  15419.     for(pixelShift = MAX_PIXEL_SHIFT; pixelShift > 0; pixelShift--) {
  15420.         int nPixels = 1 << pixelShift;
  15421.         while(deltaX >= nPixels) {
  15422.             {    /* Compute right most values of color interpolation */
  15423.                 int maxR = rValue + (deltaR << pixelShift);
  15424.                 int maxG = gValue + (deltaG << pixelShift);
  15425.                 int maxB = bValue + (deltaB << pixelShift);
  15426.                 /* Clamp those guys */
  15427.                 CLAMP_RGB(maxR, maxG, maxB);
  15428.                 /* And compute the actual delta */
  15429.                 deltaR = (maxR - rValue) >> pixelShift;
  15430.                 deltaG = (maxG - gValue) >> pixelShift;
  15431.                 deltaB = (maxB - bValue) >> pixelShift;
  15432.             }
  15433.             /* Compute the RIGHT s/t values (the left ones are kept from the last loop) */
  15434.             wValue += wDelta * nPixels;
  15435.             sValue += sDelta * nPixels;
  15436.             tValue += tDelta * nPixels;
  15437.             if(wValue) oneOverW = 1.0 / wValue;
  15438.             else oneOverW = 0.0;
  15439.             fixedRightS = (int) (sValue * oneOverW * (texture->width << B3D_IntToFixedShift));
  15440.             fixedDeltaS = (fixedRightS - fixedLeftS) >> pixelShift;
  15441.             fixedRightT = (int) (tValue * oneOverW * (texture->height << B3D_IntToFixedShift));
  15442.             fixedDeltaT = (fixedRightT - fixedLeftT) >> pixelShift;
  15443.             /* Do the inner loop */
  15444.             {    int n = nPixels;
  15445.                 while(n--) {
  15446.                     /* Do the texture load ... hmm ... there should be a way
  15447.                        to avoid loading the texture on each pixel... 
  15448.                        On the other hand, the texture load does not seem
  15449.                        too expensive if compared with the texture interpolation.
  15450.                     */
  15451.                     LOAD_4_RGB_TEXEL_32(fixedLeftS, fixedLeftT, texture);
  15452.                     /* Do the interpolation based on tex00, tex01, tex10, tex11.
  15453.                        THIS seems to be one of the real bottlenecks here...
  15454.                     */
  15455.                     INTERPOLATE_RGB_TEXEL(fixedLeftS, fixedLeftT);
  15456. #if USE_MULTBL
  15457.                     pv.redValue   = (unsigned char) (MULTBL[rValue >> (B3D_FixedToIntShift+4)][tr]);
  15458.                     pv.greenValue = (unsigned char) (MULTBL[gValue >> (B3D_FixedToIntShift+4)][tg]);
  15459.                     pv.blueValue  = (unsigned char) (MULTBL[bValue >> (B3D_FixedToIntShift+4)][tb]);
  15460. #else
  15461.                     pv.redValue   = (unsigned char) ((tr * rValue) >> (B3D_FixedToIntShift + 8));
  15462.                     pv.greenValue = (unsigned char) ((tg * gValue) >> (B3D_FixedToIntShift + 8));
  15463.                     pv.blueValue  = (unsigned char) ((tb * bValue) >> (B3D_FixedToIntShift + 8));
  15464. #endif
  15465.                     bits[leftX++] = pv;
  15466.                     rValue += deltaR;
  15467.                     gValue += deltaG;
  15468.                     bValue += deltaB;
  15469.                     fixedLeftS += fixedDeltaS;
  15470.                     fixedLeftT += fixedDeltaT;
  15471.                 }
  15472.             }
  15473.             /* Finally, adjust the number of pixels left and update s/t */
  15474.             deltaX -= nPixels;
  15475.             fixedLeftS = fixedRightS;
  15476.             fixedLeftT = fixedRightT;
  15477.         }
  15478.     }
  15479.     /* The last pixel is done separately */
  15480.     if(deltaX) {
  15481.         /* Do the texture load */
  15482.         LOAD_4_RGB_TEXEL_32(fixedLeftS, fixedLeftT, texture);
  15483.         /* Do the interpolation */
  15484.         INTERPOLATE_RGB_TEXEL(fixedLeftS, fixedLeftT);
  15485. #if USE_MULTBL
  15486.         pv.redValue   = (unsigned char) (MULTBL[rValue >> (B3D_FixedToIntShift+4)][tr]);
  15487.         pv.greenValue = (unsigned char) (MULTBL[gValue >> (B3D_FixedToIntShift+4)][tg]);
  15488.         pv.blueValue  = (unsigned char) (MULTBL[bValue >> (B3D_FixedToIntShift+4)][tb]);
  15489. #else
  15490.         pv.redValue   = (unsigned char) ((tr * rValue) >> (B3D_FixedToIntShift + 8));
  15491.         pv.greenValue = (unsigned char) ((tg * gValue) >> (B3D_FixedToIntShift + 8));
  15492.         pv.blueValue  = (unsigned char) ((tb * bValue) >> (B3D_FixedToIntShift + 8));
  15493. #endif
  15494.         bits[leftX++] = pv;
  15495.     }
  15496. }
  15497.  
  15498. void b3dDrawSTWARGB(int leftX, int rightX, int yValue, B3DPrimitiveFace *face)
  15499. {
  15500.     /* not yet implemented */
  15501. }
  15502.  
  15503. void b3dDrawRGBA(int leftX, int rightX, int yValue, B3DPrimitiveFace *face)
  15504. {
  15505.     /* not yet implemented */
  15506. }
  15507.  
  15508. void b3dDrawSTW(int leftX, int rightX, int yValue, B3DPrimitiveFace *face)
  15509. {
  15510.     /* not yet implemented */
  15511. }
  15512.  
  15513. void b3dDrawSTWA(int leftX, int rightX, int yValue, B3DPrimitiveFace *face)
  15514. {
  15515.     /* not yet implemented */
  15516. }
  15517. '! !
  15518.  
  15519. !B3DRasterizerPlugin class methodsFor: 'C source code' stamp: 'ar 4/18/1999 18:27'!
  15520. b3dHeaderH
  15521. ^'/****************************************************************************
  15522. *   PROJECT: Balloon 3D Graphics Subsystem for Squeak
  15523. *   FILE:    b3d.h
  15524. *   CONTENT: Main include file
  15525. *
  15526. *   AUTHOR:  Andreas Raab (ar)
  15527. *   ADDRESS: Walt Disney Imagineering, Glendale, CA
  15528. *   EMAIL:   andreasr@wdi.disney.com
  15529. *   RCSID:   $Id$
  15530. *
  15531. *   NOTES:
  15532. *
  15533. *
  15534. *****************************************************************************/
  15535. #ifndef __B3D_H
  15536. #define __B3D_H
  15537.  
  15538. #ifdef DEBUG
  15539. #define b3dDebug 1
  15540. #else
  15541. #define b3dDebug 0
  15542. #endif
  15543.  
  15544. #define b3dDoStats 1
  15545.  
  15546. /* primary include file */
  15547.  
  15548. #include "b3dTypes.h"
  15549. #include "b3dAlloc.h"
  15550.  
  15551. typedef int (*b3dDrawBufferFunction) (int leftX, int rightX, int yValue);
  15552.  
  15553. typedef struct B3DRasterizerState {
  15554.  
  15555.     /* The three sources for allocating 
  15556.        temporary rasterizer objects */
  15557.     B3DFaceAllocList *faceAlloc;
  15558.     B3DEdgeAllocList *edgeAlloc;
  15559.     B3DAttrAllocList *attrAlloc;
  15560.  
  15561.     /* The active edge table */
  15562.     B3DActiveEdgeTable *aet;
  15563.     /* The list for newly added edges */
  15564.     B3DPrimitiveEdgeList *addedEdges;
  15565.  
  15566.     /* The fill list */
  15567.     B3DFillList *fillList;
  15568.  
  15569.     /* The input objects for the rasterizer */
  15570.     int nObjects;
  15571.     B3DPrimitiveObject **objects;
  15572.  
  15573.     /* The input textures for the rasterizer */
  15574.     int nTextures;
  15575.     B3DTexture *textures;
  15576.  
  15577.     /* Length and location of span buffer to use */
  15578.     int spanSize;
  15579.     unsigned int *spanBuffer;
  15580.  
  15581.     /* Function to call on drawing the output buffer */
  15582.     b3dDrawBufferFunction spanDrawer;
  15583.  
  15584. } B3DRasterizerState;
  15585.  
  15586. extern B3DRasterizerState *currentState;
  15587.  
  15588. /* from b3dInit.c */
  15589. int b3dInitializeEdgeAllocator(void* base, int length);
  15590. int b3dInitializeFaceAllocator(void* base, int length);
  15591. int b3dInitializeAttrAllocator(void* base, int length);
  15592. int b3dInitializeAET(void* base, int length);
  15593. int b3dInitializeEdgeList(void* base, int length);
  15594. int b3dInitializeFillList(void* base, int length);
  15595. void b3dSetupObjects(B3DRasterizerState *state);
  15596.  
  15597. int b3dAddPolygonObject(void *objBase, int objLength, int objFlags, int textureIndex,
  15598.                           B3DPrimitiveVertex *vtxPointer, int nVertices,
  15599.                           B3DPrimitiveViewport *vp);
  15600.  
  15601. int b3dAddIndexedQuadObject(void *objBase, int objLength, int objFlags, int textureIndex,
  15602.                           B3DPrimitiveVertex *vtxPointer, int nVertices,
  15603.                           B3DInputQuad *quadPtr, int nQuads,
  15604.                           B3DPrimitiveViewport *vp);
  15605.  
  15606. int b3dAddIndexedTriangleObject(void *objBase, int objLength, int objFlags, int textureIndex,
  15607.                           B3DPrimitiveVertex *vtxPointer, int nVertices,
  15608.                           B3DInputFace *facePtr, int nFaces,
  15609.                           B3DPrimitiveViewport *vp);
  15610.  
  15611. int b3dLoadTexture(B3DTexture *texture,
  15612.                    int width, int height, int depth, unsigned int *bits,
  15613.                    int cmSize, unsigned int *colormap);
  15614.  
  15615.  
  15616. /* from b3dRemap.c */
  15617. int b3dValidateAndRemapState(B3DRasterizerState *state);
  15618.  
  15619. /* from b3dDraw.c */
  15620. typedef void (*b3dPixelDrawer) (int leftX, int rightX, int yValue, B3DPrimitiveFace *face);
  15621. extern b3dPixelDrawer B3D_FILL_FUNCTIONS[];
  15622.  
  15623. /* from b3dMain.c */
  15624. void b3dAbort(char *msg);
  15625. int b3dMainLoop(B3DRasterizerState *state, int stopReason);
  15626.  
  15627. #endif
  15628. '! !
  15629.  
  15630. !B3DRasterizerPlugin class methodsFor: 'C source code' stamp: 'ar 4/21/1999 00:31'!
  15631. b3dInitC
  15632. ^'/****************************************************************************
  15633. *   PROJECT: Balloon 3D Graphics Subsystem for Squeak
  15634. *   FILE:    b3dInit.c
  15635. *   CONTENT: Initialization functions for the B3D rasterizer
  15636. *
  15637. *   AUTHOR:  Andreas Raab (ar)
  15638. *   ADDRESS: Walt Disney Imagineering, Glendale, CA
  15639. *   EMAIL:   andreasr@wdi.disney.com
  15640. *   RCSID:   $Id$
  15641. *
  15642. *   NOTES:
  15643. *
  15644. *
  15645. *****************************************************************************/
  15646. #include <string.h>
  15647. #include "b3d.h"
  15648.  
  15649. #define b3dCompensateWindowPos 1
  15650.  
  15651. /* helpers */
  15652. #define rasterPosX rasterPos[0]
  15653. #define rasterPosY rasterPos[1]
  15654. #define rasterPosZ rasterPos[2]
  15655. #define rasterPosW rasterPos[3]
  15656.  
  15657. #define windowPosX windowPos[0]
  15658. #define windowPosY windowPos[1]
  15659.  
  15660. #define texCoordS texCoord[0]
  15661. #define texCoordT texCoord[1]
  15662.  
  15663. /*************************************************************/
  15664. /*************************************************************/
  15665. /*************************************************************/
  15666. int b3dInitializeEdgeAllocator(void* base, int length)
  15667. {
  15668.     B3DEdgeAllocList *list = (B3DEdgeAllocList*) base;
  15669.     if(length < sizeof(B3DEdgeAllocList))
  15670.         return B3D_GENERIC_ERROR;
  15671.     list->magic = B3D_EDGE_ALLOC_MAGIC;
  15672.     list->This = base;
  15673.     list->max = (length - sizeof(B3DEdgeAllocList)) / sizeof(B3DPrimitiveEdge) + 1;
  15674.     list->size = 0;
  15675.     list->nFree = list->max;
  15676.     list->firstFree = NULL;
  15677.     return B3D_NO_ERROR;
  15678. }
  15679.  
  15680. int b3dInitializeFaceAllocator(void* base, int length)
  15681. {
  15682.     B3DFaceAllocList *list = (B3DFaceAllocList*) base;
  15683.     if(length < sizeof(B3DFaceAllocList))
  15684.         return B3D_GENERIC_ERROR;
  15685.     list->magic = B3D_FACE_ALLOC_MAGIC;
  15686.     list->This = base;
  15687.     list->max = (length - sizeof(B3DFaceAllocList)) / sizeof(B3DPrimitiveFace) + 1;
  15688.     list->size = 0;
  15689.     list->nFree = list->max;
  15690.     list->firstFree = NULL;
  15691.     return B3D_NO_ERROR;
  15692. }
  15693.  
  15694. int b3dInitializeAttrAllocator(void* base, int length)
  15695. {
  15696.     B3DAttrAllocList *list = (B3DAttrAllocList*) base;
  15697.     if(length < sizeof(B3DAttrAllocList))
  15698.         return B3D_GENERIC_ERROR;
  15699.     list->magic = B3D_ATTR_ALLOC_MAGIC;
  15700.     list->This = base;
  15701.     list->max = (length - sizeof(B3DAttrAllocList)) / sizeof(B3DPrimitiveAttribute) + 1;
  15702.     list->size = 0;
  15703.     list->nFree = list->max;
  15704.     list->firstFree = NULL;
  15705.     return B3D_NO_ERROR;
  15706. }
  15707.  
  15708. int b3dInitializeEdgeList(void* base, int length)
  15709. {
  15710.     B3DPrimitiveEdgeList *list = (B3DPrimitiveEdgeList*) base;
  15711.     if(length < sizeof(B3DPrimitiveEdgeList))
  15712.         return B3D_GENERIC_ERROR;
  15713.     list->magic = B3D_EDGE_LIST_MAGIC;
  15714.     list->This = base;
  15715.     list->max = (length - sizeof(B3DPrimitiveEdgeList)) / sizeof(B3DPrimitiveEdge*) + 1;
  15716.     list->size = 0;
  15717.     return B3D_NO_ERROR;
  15718. }
  15719.  
  15720. int b3dInitializeAET(void* base, int length)
  15721. {
  15722.     B3DActiveEdgeTable *aet = (B3DActiveEdgeTable *) base;
  15723.     if(length < sizeof(B3DActiveEdgeTable))
  15724.         return B3D_GENERIC_ERROR;
  15725.     aet->magic = B3D_AET_MAGIC;
  15726.     aet->This = base;
  15727.     aet->max = (length - sizeof(B3DActiveEdgeTable)) / sizeof(B3DPrimitiveEdge*) + 1;
  15728.     aet->size = 0;
  15729.     aet->leftEdge = aet->rightEdge = NULL;
  15730.     aet->lastIntersection = &aet->tempEdge0;
  15731.     aet->nextIntersection = &aet->tempEdge1;
  15732.     return B3D_NO_ERROR;
  15733. }
  15734.  
  15735. int b3dInitializeFillList(void* base, int length)
  15736. {
  15737.     B3DFillList *list = (B3DFillList*) base;
  15738.     if(length < sizeof(B3DFillList))
  15739.         return B3D_GENERIC_ERROR;
  15740.     list->magic = B3D_FILL_LIST_MAGIC;
  15741.     list->This = base;
  15742.     list->firstFace = list->lastFace = NULL;
  15743.     return B3D_NO_ERROR;
  15744. }
  15745.  
  15746. /*************************************************************/
  15747. /*************************************************************/
  15748. /*************************************************************/
  15749.  
  15750. /* b3dMapObjectVertices:
  15751.      Map all the vertices of the given object into the designated viewport.
  15752. */
  15753. void b3dMapObjectVertices(B3DPrimitiveObject *obj, B3DPrimitiveViewport *vp)
  15754. {
  15755.     double xScale, yScale, xOfs, yOfs;
  15756.     int minX, minY, maxX, maxY;
  15757.     double minZ, maxZ;
  15758.     B3DPrimitiveVertex *vtx;
  15759.     int i;
  15760.  
  15761.     xOfs = (vp->x0 + vp->x1) * 0.5 - 0.5;
  15762.     yOfs = (vp->y0 + vp->y1) * 0.5 - 0.5;
  15763.     xScale = (vp->x1 - vp->x0) * 0.5;
  15764.     yScale = (vp->y1 - vp->y0) * -0.5;
  15765.  
  15766.     minX = minY = maxX = maxY = 0x7FFFFFFF;
  15767.     minZ = maxZ = 0.0;
  15768.     vtx = obj->vertices + 1;
  15769.     for(i=1; i < obj->nVertices; i++, vtx++)
  15770.     {
  15771.         double x,y,z,w;
  15772.         int scaledX, scaledY;
  15773.  
  15774.         w = vtx->rasterPosW;
  15775.         if(w) w = 1.0 / w;
  15776.         x = vtx->rasterPosX * w * xScale + xOfs;
  15777.         y = vtx->rasterPosY * w * yScale + yOfs;
  15778.         z = vtx->rasterPosZ * w;
  15779.  
  15780.         if(!!b3dCompensateWindowPos) {
  15781.             vtx->rasterPosX = (float)x;
  15782.             vtx->rasterPosY = (float)y;
  15783.         }
  15784.         vtx->rasterPosZ = (float)z;
  15785.         vtx->rasterPosW = (float)w;
  15786.  
  15787.         scaledX = (int) (x * B3D_FloatToFixed);
  15788.         scaledY = (int) (y * B3D_FloatToFixed);
  15789.  
  15790.         vtx->windowPosX = scaledX;
  15791.         vtx->windowPosY = scaledY;
  15792.         if(b3dCompensateWindowPos) {
  15793.             vtx->rasterPosX = (float) (scaledX * B3D_FixedToFloat);
  15794.             vtx->rasterPosY = (float) (scaledY * B3D_FixedToFloat);
  15795.         }
  15796.         /* Update min/max */
  15797.         if(i == 1) {
  15798.             minX = maxX = scaledX;
  15799.             minY = maxY = scaledY;
  15800.             minZ = maxZ = z;
  15801.         } else {
  15802.             if(scaledX < minX) minX = scaledX;
  15803.             else if(scaledX > maxX) maxX = scaledX;
  15804.             if(scaledY < minY) minY = scaledY;
  15805.             else if(scaledY > maxY) maxY = scaledY;
  15806.             if(z < minZ) minZ = z;
  15807.             else if(z > maxZ) maxZ = z;
  15808.         }
  15809.  
  15810.     }
  15811.  
  15812.     obj->minX = minX >> B3D_FixedToIntShift;
  15813.     obj->maxX = maxX >> B3D_FixedToIntShift;
  15814.     obj->minY = minY >> B3D_FixedToIntShift;
  15815.     obj->maxY = maxY >> B3D_FixedToIntShift;
  15816.     obj->minZ = (float)minZ;
  15817.     obj->maxZ = (float)maxZ;
  15818. }
  15819.  
  15820. /* b3dSetupVertexOrder:
  15821.      Setup the ordering of the vertices in each face so that
  15822.        v0 sorts before v1 sorts before v2.
  15823.      Gather some stats on how much locally sorted and invalid
  15824.      faces the object includes.
  15825. */
  15826.  
  15827. void b3dSetupVertexOrder(B3DPrimitiveObject *obj)
  15828. {
  15829.     B3DInputFace *face;
  15830.     int i, nSorted, nInvalid;
  15831.     B3DPrimitiveVertex *vtx, *lastTopVtx, *newTopVtx;
  15832.  
  15833.     face = obj->faces;
  15834.     vtx = obj->vertices;
  15835.     nSorted = nInvalid = 0;
  15836.     lastTopVtx = NULL;
  15837.     for(i=0;i<obj->nFaces; i++,face++)
  15838.     {
  15839.         B3DPrimitiveVertex *vtx0, *vtx1, *vtx2;
  15840.         int idx0, idx1, idx2;
  15841.         idx0 = face->i0;
  15842.         idx1 = face->i1;
  15843.         idx2 = face->i2;
  15844.         if(0 == (idx0 && idx1 && idx2)) {
  15845.             nInvalid++;
  15846.             continue;
  15847.         }
  15848.         vtx0 = vtx + idx0;
  15849.         vtx1 = vtx + idx1;
  15850.         vtx2 = vtx + idx2;
  15851.         if(vtxSortsBefore(vtx0,vtx1))
  15852.         {
  15853.             if(vtxSortsBefore(vtx1,vtx2)) { 
  15854.                 face->i0 = idx0; 
  15855.                 face->i1 = idx1; 
  15856.                 face->i2 = idx2; 
  15857.             } else if(vtxSortsBefore(vtx0,vtx2)) {
  15858.                 face->i0 = idx0;
  15859.                 face->i1 = idx2;
  15860.                 face->i2 = idx1;
  15861.             } else {
  15862.                 face->i0 = idx2;
  15863.                 face->i1 = idx0;
  15864.                 face->i2 = idx1;
  15865.             }
  15866.         } else if(vtxSortsBefore(vtx0, vtx2)) {
  15867.             face->i0 = idx1;
  15868.             face->i1 = idx0;
  15869.             face->i2 = idx2;
  15870.         } else if(vtxSortsBefore(vtx1, vtx2)) {
  15871.             face->i0 = idx1;
  15872.             face->i1 = idx2;
  15873.             face->i2 = idx0;
  15874.         } else {
  15875.             face->i0 = idx2;
  15876.             face->i1 = idx1;
  15877.             face->i2 = idx0;
  15878.         }
  15879.  
  15880.         if(b3dDebug) {
  15881.             vtx0 = vtx + face->i0;
  15882.             vtx1 = vtx + face->i1;
  15883.             vtx2 = vtx + face->i2;
  15884.             if( !!vtxSortsBefore(vtx0, vtx1) || 
  15885.                 !!vtxSortsBefore(vtx0, vtx2) || 
  15886.                 !!vtxSortsBefore(vtx1, vtx2))
  15887.                     b3dAbort("Vertex order problem");
  15888.         }
  15889.  
  15890.         /* Experimental: Try to estimate how many faces are already sorted. */
  15891.         newTopVtx = vtx + face->i0;
  15892.         if(lastTopVtx)
  15893.             if(vtxSortsBefore(lastTopVtx, newTopVtx)) nSorted++;
  15894.         lastTopVtx = newTopVtx;
  15895.     }
  15896.  
  15897.     obj->nSortedFaces = nSorted;
  15898.     obj->nInvalidFaces = nInvalid;
  15899. }
  15900.  
  15901. /* b3dSortInitialFaces:
  15902.      Sort the faces of the given object according to the given sort order.
  15903.      Note: It is assumed that the vertex order of the faces has been setup
  15904.            before.
  15905. */
  15906.  
  15907. void b3dQuickSortInitialFaces(B3DPrimitiveObject *obj, int i, int j)
  15908. {
  15909.     B3DInputFace tmp, *faces = obj->faces;
  15910.     int ij, k, l, n;
  15911.     B3DPrimitiveVertex *di, *dj, *dij, *tt, *vtx = obj->vertices;
  15912.  
  15913.     n = j + 1 - i;
  15914.     if(n <= 1) return;
  15915.     /* Sort di,dj. */
  15916.     di = vtx + faces[i].i0;
  15917.     dj = vtx + faces[j].i0;
  15918.     if(!!vtxSortsBefore(di,dj))
  15919.     {
  15920.         tmp = faces[i]; faces[i] = faces[j]; faces[j] = tmp;
  15921.         tt = di; di = dj; dj = tt;
  15922.     }
  15923.  
  15924.     if(n <= 2) return;
  15925.  
  15926.     /* More than two elements. */
  15927.     ij = (i+j) >> 1; /* ij is the midpoint of i and j. */
  15928.     dij = vtx + faces[ij].i0;
  15929.     /* Sort di,dij,dj.  Make dij be their median. */
  15930.     if(vtxSortsBefore(di, dij)) {/* i.e. should di precede dij? */
  15931.         if(!!vtxSortsBefore(dij, dj)) {/* i.e., should dij precede dj?*/
  15932.             tmp = faces[j]; faces[j] = faces[ij]; faces[ij] = tmp;
  15933.             dij = dj;
  15934.         }
  15935.     } else { /* i.e. di should come after dij */
  15936.         tmp = faces[i]; faces[i] = faces[ij]; faces[ij] = tmp;
  15937.         dij = di;
  15938.     }
  15939.  
  15940.     if(n <= 3) return;
  15941.  
  15942.     /* More than three elements.
  15943.     Find k>i and l<j such that dk,dij,dl are in reverse order.
  15944.     Swap k and l.  Repeat this procedure until k and l pass each other.*/
  15945.     k = i;
  15946.     l = j;
  15947.  
  15948.     while(k <= l) {
  15949.         while(k <= --l && (vtxSortsBefore(dij, vtx + faces[l].i0)));
  15950.         while(++k <= l && (vtxSortsBefore(vtx + faces[k].i0, dij)));
  15951.         if(k <= l) {
  15952.             tmp = faces[k];
  15953.             faces[k] = faces[l];
  15954.             faces[l] = tmp;
  15955.         }
  15956.     }
  15957.     /* Now l<k (either 1 or 2 less), and di through dl are all less than or equal to dk
  15958.     through dj.  Sort those two segments. */
  15959.     b3dQuickSortInitialFaces(obj, i, l);
  15960.     b3dQuickSortInitialFaces(obj, k, j);
  15961. }
  15962.  
  15963. /*************************************************************/
  15964. /*************************************************************/
  15965. /*************************************************************/
  15966.  
  15967.  
  15968. void b3dValidateObjectFaces(B3DPrimitiveObject *obj)
  15969. {
  15970.     int i;
  15971.     B3DInputFace *face,*nextFace;
  15972.  
  15973.     face = obj->faces;
  15974.     nextFace = face + 1;
  15975.     for(i=1; i < obj->nFaces; i++, face++, nextFace++) {
  15976.         if(!!vtxSortsBefore(obj->vertices + face->i0, obj->vertices + nextFace->i0))
  15977.             b3dAbort("Face sorting problem");
  15978.     }
  15979. }
  15980.  
  15981.  
  15982. #define InitObject(obj, objBase, objFlags, textureIndex) \
  15983.     obj = (B3DPrimitiveObject*) objBase; \
  15984.     obj->magic = B3D_PRIMITIVE_OBJECT_MAGIC; \
  15985.     obj->This = objBase; \
  15986.     obj->start = 0; \
  15987.     obj->next = NULL; \
  15988.     obj->flags = objFlags; \
  15989.     obj->textureIndex = textureIndex; \
  15990.     obj->texture = NULL;
  15991.  
  15992. #define InitVertex(vtx) \
  15993.         (vtx)->rasterPosX =                \
  15994.         (vtx)->rasterPosY =                \
  15995.         (vtx)->rasterPosZ =                \
  15996.         (vtx)->rasterPosW =                \
  15997.         (vtx)->texCoordS  =                \
  15998.         (vtx)->texCoordT  = (float) 0.0;\
  15999.         (vtx)->windowPosX =                \
  16000.         (vtx)->windowPosY = 0x7FFFFFFF;    \
  16001.         (vtx)->cc.pixelValue32 = 0;
  16002.  
  16003.  
  16004. /* b3dAddIndexedTriangleObject:
  16005.      Create a new primitive object.
  16006. */
  16007. int b3dAddIndexedTriangleObject(void *objBase, int objLength, int objFlags, int textureIndex,
  16008.                           B3DPrimitiveVertex *vtxPointer, int nVertices,
  16009.                           B3DInputFace *facePtr, int nFaces,
  16010.                           B3DPrimitiveViewport *vp)
  16011. {
  16012.     B3DPrimitiveObject *obj;
  16013.     int sizeNeeded;
  16014.  
  16015.     sizeNeeded = sizeof(B3DPrimitiveObject) + 
  16016.                  sizeof(B3DPrimitiveVertex) * (nVertices+1) +
  16017.                  sizeof(B3DInputFace) * nFaces;
  16018.  
  16019.     if(!!objBase || objLength < sizeNeeded) 
  16020.         return B3D_GENERIC_ERROR;
  16021.  
  16022.     InitObject(obj, objBase, objFlags, textureIndex);
  16023.  
  16024.     /* copy in the primitive vertices (starting immediately after the prim object) */
  16025.     obj->nVertices = nVertices+1; /* For one-based indexing leave one more entry */
  16026.     obj->vertices = (B3DPrimitiveVertex*) (obj + 1);
  16027.     memcpy(obj->vertices+1, vtxPointer, nVertices * sizeof(B3DPrimitiveVertex));
  16028.  
  16029.     /* copy in the input faces (starting after the vertices) */
  16030.     obj->nFaces = nFaces;
  16031.     obj->faces = (B3DInputFace*) (obj->vertices + obj->nVertices);
  16032.     memcpy(obj->faces, facePtr, nFaces * sizeof(B3DInputFace));
  16033.  
  16034.     /* Initialize the first vertex with something useful */
  16035.     InitVertex(obj->vertices);
  16036.     b3dMapObjectVertices(obj, vp);
  16037.     b3dSetupVertexOrder(obj);
  16038.     b3dQuickSortInitialFaces(obj,0,obj->nFaces-1);
  16039.  
  16040.  
  16041.     if(b3dDebug)
  16042.         b3dValidateObjectFaces(obj);
  16043.  
  16044.     return B3D_NO_ERROR;
  16045. }
  16046.  
  16047. /* b3dAddIndexedQuadObject:
  16048.      Create a new primitive object.
  16049. */
  16050. int b3dAddIndexedQuadObject(void *objBase, int objLength, int objFlags, int textureIndex,
  16051.                           B3DPrimitiveVertex *vtxPointer, int nVertices,
  16052.                           B3DInputQuad *quadPtr, int nQuads,
  16053.                           B3DPrimitiveViewport *vp)
  16054. {
  16055.     B3DPrimitiveObject *obj;
  16056.     int sizeNeeded;
  16057.  
  16058.     sizeNeeded = sizeof(B3DPrimitiveObject) + 
  16059.                  sizeof(B3DPrimitiveVertex) * (nVertices+1) +
  16060.                  sizeof(B3DInputFace) * nQuads * 2;
  16061.  
  16062.     if(!!objBase || objLength < sizeNeeded) 
  16063.         return B3D_GENERIC_ERROR;
  16064.  
  16065.     InitObject(obj, objBase, objFlags, textureIndex);
  16066.  
  16067.     /* copy in the primitive vertices (starting immediately after the prim object) */
  16068.     obj->nVertices = nVertices+1; /* For one-based indexing leave one more entry */
  16069.     obj->vertices = (B3DPrimitiveVertex*) (obj + 1);
  16070.     memcpy(obj->vertices+1, vtxPointer, nVertices * sizeof(B3DPrimitiveVertex));
  16071.  
  16072.     /* copy in the input faces (starting after the vertices) */
  16073.     obj->nFaces = nQuads * 2;
  16074.     obj->faces = (B3DInputFace*) (obj->vertices + obj->nVertices);
  16075.     {
  16076.         int i, nFaces = obj->nFaces;
  16077.         B3DInputQuad *src = quadPtr;
  16078.         B3DInputFace *dst = obj->faces;
  16079.  
  16080.         for(i=0; i < nFaces; i++, src++) {
  16081.             dst->i0 = src->i0;
  16082.             dst->i1 = src->i1;
  16083.             dst->i2 = src->i2;
  16084.             dst++;
  16085.             dst->i0 = src->i2;
  16086.             dst->i1 = src->i3;
  16087.             dst->i2 = src->i0;
  16088.             dst++;
  16089.         }
  16090.     }
  16091.  
  16092.     /* Initialize the first vertex with something useful */
  16093.     InitVertex(obj->vertices);
  16094.     b3dMapObjectVertices(obj, vp);
  16095.     b3dSetupVertexOrder(obj);
  16096.     b3dQuickSortInitialFaces(obj,0,obj->nFaces-1);
  16097.  
  16098.     if(b3dDebug)
  16099.         b3dValidateObjectFaces(obj);
  16100.  
  16101.     return B3D_NO_ERROR;
  16102. }
  16103.  
  16104. /* b3dAddPolygonObject:
  16105.      Create a new primitive object.
  16106. */
  16107. int b3dAddPolygonObject(void *objBase, int objLength, int objFlags, int textureIndex,
  16108.                           B3DPrimitiveVertex *vtxPointer, int nVertices,
  16109.                           B3DPrimitiveViewport *vp)
  16110. {
  16111.     B3DPrimitiveObject *obj;
  16112.     int sizeNeeded;
  16113.  
  16114.     sizeNeeded = sizeof(B3DPrimitiveObject) + 
  16115.                  sizeof(B3DPrimitiveVertex) * (nVertices+1) +
  16116.                  sizeof(B3DInputFace) * (nVertices - 2);
  16117.  
  16118.     if(!!objBase || objLength < sizeNeeded) 
  16119.         return B3D_GENERIC_ERROR;
  16120.  
  16121.     InitObject(obj, objBase, objFlags, textureIndex);
  16122.  
  16123.     /* copy in the primitive vertices (starting immediately after the prim object) */
  16124.     obj->nVertices = nVertices+1; /* For one-based indexing leave one more entry */
  16125.     obj->vertices = (B3DPrimitiveVertex*) (obj + 1);
  16126.     memcpy(obj->vertices+1, vtxPointer, nVertices * sizeof(B3DPrimitiveVertex));
  16127.  
  16128.     /* copy in the input faces (starting after the vertices) */
  16129.     obj->nFaces = nVertices - 2;
  16130.     obj->faces = (B3DInputFace*) (obj->vertices + obj->nVertices);
  16131.     {
  16132.         B3DInputFace *dst = obj->faces;
  16133.         int i, nFaces = obj->nFaces;
  16134.  
  16135.         for(i=0; i < nFaces; i++, dst++) {
  16136.             dst->i0 = 1;
  16137.             dst->i1 = 2+i;
  16138.             dst->i2 = 3+i;
  16139.         }
  16140.     }
  16141.  
  16142.     /* Initialize the first vertex with something useful */
  16143.     InitVertex(obj->vertices);
  16144.     b3dMapObjectVertices(obj, vp);
  16145.     b3dSetupVertexOrder(obj);
  16146.     b3dQuickSortInitialFaces(obj,0,obj->nFaces-1);
  16147.  
  16148.     if(b3dDebug)
  16149.         b3dValidateObjectFaces(obj);
  16150.  
  16151.     return B3D_NO_ERROR;
  16152. }
  16153.  
  16154. /*************************************************************/
  16155. /*************************************************************/
  16156. /*************************************************************/
  16157.  
  16158. int b3dLoadTexture(B3DTexture *texture,
  16159.                    int width, int height, int depth, unsigned int *bits,
  16160.                    int cmSize, unsigned int *colormap)
  16161. {    int nBits;
  16162.  
  16163.     if(width < 1 || height < 1) return B3D_GENERIC_ERROR;
  16164.     if(depth !!= 32) return B3D_GENERIC_ERROR;
  16165.     if(depth !!= 8  && depth !!= 16 && depth !!= 32) return B3D_GENERIC_ERROR;
  16166.     if(depth == 8 && cmSize < 256) return B3D_GENERIC_ERROR;
  16167.     texture->width = width;
  16168.     texture->height = height;
  16169.     texture->depth = depth;
  16170.     texture->data = bits;
  16171.     texture->cmSize = cmSize;
  16172.     texture->colormap = colormap;
  16173.     texture->rowLength = width;
  16174.     nBits = 1;
  16175.     while((1 << nBits) < width) nBits++;
  16176.     if((1<<nBits) == width) {
  16177.         texture->sMask = (1<<nBits) - 1;
  16178.         texture->sShift = nBits;
  16179.     } else {
  16180.         texture->sMask = texture->sShift = 0;
  16181.     }
  16182.     while((1 << nBits) < height) nBits++;
  16183.     if((1<<nBits) == height) {
  16184.         texture->tMask = (1<<nBits) - 1;
  16185.         texture->tShift = nBits;
  16186.     } else {
  16187.         texture->tMask = texture->tShift = 0;
  16188.     }
  16189.     return B3D_NO_ERROR;
  16190. }
  16191. /*************************************************************/
  16192. /*************************************************************/
  16193. /*************************************************************/
  16194. /* b3dQuickSortObjects:
  16195.     Sort the objects in the given range.
  16196. */
  16197.  
  16198. void b3dQuickSortObjects(B3DPrimitiveObject **array, int i, int j)
  16199. {
  16200.     int ij, k, l, n;
  16201.     B3DPrimitiveObject *di, *dj, *dij, *tmp;
  16202.     
  16203.     n = j + 1 - i;
  16204.     if(n <= 1) return;
  16205.     /* Sort di,dj. */
  16206.     di = array[i];
  16207.     dj = array[j];
  16208.     if(!!objSortsBefore(di,dj))
  16209.     {
  16210.         tmp = array[i]; array[i] = array[j]; array[j] = tmp;
  16211.         tmp = di; di = dj; dj = tmp;
  16212.     }
  16213.  
  16214.     if(n <= 2) return;
  16215.  
  16216.     /* More than two elements. */
  16217.     ij = (i+j) >> 1; /* ij is the midpoint of i and j. */
  16218.     dij = array[ij];
  16219.     /* Sort di,dij,dj.  Make dij be their median. */
  16220.     if(objSortsBefore(di, dij)) {/* i.e. should di precede dij? */
  16221.         if(!!objSortsBefore(dij, dj)) {/* i.e., should dij precede dj?*/
  16222.             tmp = array[j]; array[j] = array[ij]; array[ij] = tmp;
  16223.             dij = dj;
  16224.         }
  16225.     } else { /* i.e. di should come after dij */
  16226.         tmp = array[i]; array[i] = array[ij]; array[ij] = tmp;
  16227.         dij = di;
  16228.     }
  16229.  
  16230.     if(n <= 3) return;
  16231.  
  16232.     /* More than three elements.
  16233.     Find k>i and l<j such that dk,dij,dl are in reverse order.
  16234.     Swap k and l.  Repeat this procedure until k and l pass each other.*/
  16235.     k = i;
  16236.     l = j;
  16237.  
  16238.     while(k <= l) {
  16239.         while(k <= --l && (objSortsBefore(dij, array[l])));
  16240.         while(++k <= l && (objSortsBefore(array[k], dij)));
  16241.         if(k <= l) { tmp = array[k]; array[k] = array[l]; array[l] = tmp; }
  16242.     }
  16243.     /* Now l<k (either 1 or 2 less), and di through dl are all less than or equal to dk
  16244.     through dj.  Sort those two segments. */
  16245.     b3dQuickSortObjects(array, i, l);
  16246.     b3dQuickSortObjects(array, k, j);
  16247. }
  16248.  
  16249. /* b3dSetupObjects:
  16250.     Sort the objects and create a linked list between the objects.
  16251. */
  16252. void b3dSetupObjects(B3DRasterizerState *state)
  16253. {
  16254.     int i, textureIndex, nTextures = state->nTextures, nObjects = state->nObjects;
  16255.     B3DPrimitiveObject *obj, **objects = state->objects;
  16256.     B3DTexture *textures = state->textures;
  16257.  
  16258.     b3dQuickSortObjects(objects, 0, nObjects-1);
  16259.  
  16260.     for(i=0; i<nObjects; i++) {
  16261.  
  16262.         if(b3dDebug && i) {
  16263.             if(!!objSortsBefore(objects[i-1], objects[i]))
  16264.                 b3dAbort("Object sorting problem");
  16265.         }
  16266.  
  16267.         obj = objects[i];
  16268.         obj->flags &= ~(B3D_OBJECT_ACTIVE | B3D_OBJECT_DONE);
  16269.         obj->start = 0;
  16270.         /*-- Note: The following is important --*/
  16271.         obj->nFaces -= obj->nInvalidFaces;
  16272.         if(!!obj->nFaces) break;
  16273.         /*-- End --*/
  16274.         textureIndex = obj->textureIndex - 1;
  16275.         if(textureIndex >= 0 && textureIndex < nTextures) {
  16276.             obj->texture = textures + textureIndex;
  16277.             obj->flags |= B3D_FACE_STW;
  16278.         } else obj->texture = NULL;
  16279.         obj->next = NULL;
  16280.         if(i) {
  16281.             objects[i-1]->next = obj;
  16282.             obj->prev = objects[i-1];
  16283.         }
  16284.     }
  16285. }
  16286. '! !
  16287.  
  16288. !B3DRasterizerPlugin class methodsFor: 'C source code' stamp: 'ar 4/18/1999 08:33'!
  16289. b3dMainC
  16290. ^'/****************************************************************************
  16291. *   PROJECT: Balloon 3D Graphics Subsystem for Squeak
  16292. *   FILE:    b3dMain.c
  16293. *   CONTENT: Main rasterizer body
  16294. *
  16295. *   AUTHOR:  Andreas Raab (ar)
  16296. *   ADDRESS: Walt Disney Imagineering, Glendale, CA
  16297. *   EMAIL:   andreasr@wdi.disney.com
  16298. *   RCSID:   $Id$
  16299. *
  16300. *   NOTES:
  16301. *
  16302. *
  16303. *****************************************************************************/
  16304. #include <stdio.h>  /* printf() */
  16305. #include <stdlib.h> /* exit()   */
  16306. #include <assert.h> /* assert() */
  16307. #include "b3d.h"
  16308.  
  16309. #ifndef NULL
  16310. #define NULL ((void*)0)
  16311. #endif
  16312.  
  16313. #ifdef B3D_PROFILE
  16314. unsigned int b3dObjSetupTime;
  16315. unsigned int b3dMapObjectTime;
  16316. unsigned int b3dVertexOrderTime;
  16317. unsigned int b3dSortFaceTime;
  16318. #endif
  16319.  
  16320. /* helpers */
  16321. #define rasterPosX rasterPos[0]
  16322. #define rasterPosY rasterPos[1]
  16323. #define rasterPosZ rasterPos[2]
  16324. #define rasterPosW rasterPos[3]
  16325.  
  16326. #define windowPosX windowPos[0]
  16327. #define windowPosY windowPos[1]
  16328.  
  16329. #define texCoordS texCoord[0]
  16330. #define texCoordT texCoord[1]
  16331.  
  16332. #define redValue   cc.color[RED_INDEX]
  16333. #define greenValue cc.color[GREEN_INDEX]
  16334. #define blueValue  cc.color[BLUE_INDEX]
  16335. #define alphaValue cc.color[ALPHA_INDEX]
  16336.  
  16337. /* globals */
  16338. B3DRasterizerState *currentState;
  16339.  
  16340. B3DActiveEdgeTable *aet;
  16341. B3DPrimitiveEdgeList *addedEdges;
  16342.  
  16343. B3DEdgeAllocList *edgeAlloc;
  16344. B3DFaceAllocList *faceAlloc;
  16345. B3DAttrAllocList *attrAlloc;
  16346.  
  16347. int nFaces = 0;
  16348. int maxFaces = 0;
  16349. int maxEdges = 0;
  16350. /*************************************************************/
  16351. /*************************************************************/
  16352. /*************************************************************/
  16353.  
  16354. void b3dAbort(char *msg){
  16355.     printf(msg);
  16356.     exit(-1);
  16357. }
  16358.  
  16359. void b3dValidateEdgeOrder(B3DPrimitiveEdgeList *list)
  16360. {
  16361.     int i;
  16362.  
  16363.     if(list->size)
  16364.         if(list->data[0]->leftFace == list->data[0]->rightFace) {
  16365.             b3dAbort("Left face == right face");
  16366.         }
  16367.     for(i=1; i<list->size; i++) {
  16368.         if(list->data[i-1]->xValue > list->data[i]->xValue) {
  16369.             b3dAbort("Edge list is broken");
  16370.         }
  16371.         if(list->data[i]->leftFace == list->data[i]->rightFace) {
  16372.             b3dAbort("Left face == right face");
  16373.         }
  16374.     }
  16375. }
  16376.  
  16377. void b3dValidateAETOrder(B3DActiveEdgeTable *list)
  16378. {
  16379.     int i;
  16380.  
  16381.     if(list->size)
  16382.         if(list->data[0]->leftFace == list->data[0]->rightFace) {
  16383.             b3dAbort("Left face == right face");
  16384.         }
  16385.     for(i=1; i<list->size; i++) {
  16386.         if(list->data[i-1]->xValue > list->data[i]->xValue) {
  16387.             b3dAbort("Edge list is broken");
  16388.         }
  16389.         if(list->data[i]->leftFace == list->data[i]->rightFace) {
  16390.             b3dAbort("Left face == right face");
  16391.         }
  16392.     }
  16393. }
  16394.  
  16395. /*************************************************************/
  16396. /*************************************************************/
  16397. /*************************************************************/
  16398. /* b3dInitializeFace:
  16399.     Allocate a new primitive face based on the given vertices.
  16400.     Do the necessary initial setup, but don''t set up any drawing attributes yet.
  16401.     Return the newly created face.
  16402.     NOTE: May cause allocation of one face!!
  16403. */
  16404. B3DPrimitiveFace *b3dInitializeFace(B3DPrimitiveVertex *v0,
  16405.                                     B3DPrimitiveVertex *v1,
  16406.                                     B3DPrimitiveVertex *v2,
  16407.                                     B3DTexture *texture, 
  16408.                                     int attrFlags)
  16409. {
  16410.     B3DPrimitiveFace *face;
  16411.  
  16412.     /* Compute major and minor reference edges */
  16413.     {
  16414.         float majorDx = v2->rasterPosX - v0->rasterPosX;
  16415.         float majorDy = v2->rasterPosY - v0->rasterPosY;
  16416.         float minorDx = v1->rasterPosX - v0->rasterPosX;
  16417.         float minorDy = v1->rasterPosY - v0->rasterPosY;
  16418.         float area = (majorDx * minorDy) - (minorDx * majorDy);
  16419.  
  16420.         if(area > -0.001 && area < 0.001) return NULL;
  16421.         /* Now that we know the face is valid, do the actual allocation */
  16422.         b3dAllocFace(faceAlloc, face);
  16423.  
  16424.         if(b3dDebug)
  16425.             if(!!face) b3dAbort("Face allocation failed");
  16426.  
  16427.         face->v0 = v0;
  16428.         face->v1 = v1;
  16429.         face->v2 = v2;
  16430.         face->leftEdge = NULL;
  16431.         face->rightEdge = NULL;
  16432.         face->attributes = NULL;
  16433.         face->oneOverArea = (float) (1.0 / area);
  16434.         face->majorDx = majorDx;
  16435.         face->majorDy = majorDy;
  16436.         face->minorDx = minorDx;
  16437.         face->minorDy = minorDy;
  16438.         face->texture = texture;
  16439.         face->flags |= attrFlags & (B3D_ATTR_MASK << B3D_ATTR_SHIFT);
  16440.  
  16441.         { /* Compute dzdx and dzdy */
  16442.             float majorDz = v2->rasterPosZ - v0->rasterPosZ;
  16443.             float minorDz = v1->rasterPosZ - v0->rasterPosZ;
  16444.  
  16445.             face->dzdx = face->oneOverArea * ((majorDz * minorDy) - (minorDz * majorDy));
  16446.             face->dzdy = face->oneOverArea * ((majorDx * minorDz) - (minorDx * majorDz));
  16447.         }
  16448.     }
  16449.  
  16450.     {/* Compute minZ/maxZ */
  16451.         float z0 = v0->rasterPosZ;
  16452.         float z1 = v1->rasterPosZ;
  16453.         float z2 = v2->rasterPosZ;
  16454.         if(z0 <= z1) {
  16455.             if(z1 <= z2) {
  16456.                 face->minZ = z0;
  16457.                 face->maxZ = z2;
  16458.             } else if(z0 <= z2) {
  16459.                 face->minZ = z0;
  16460.                 face->maxZ = z1;
  16461.             } else {
  16462.                 face->minZ = z2;
  16463.                 face->maxZ = z1;
  16464.             }
  16465.         } else if(z2 <= z1) {
  16466.             face->minZ = z2;
  16467.             face->maxZ = z0;
  16468.         } else if(z0 <= z2) {
  16469.             face->minZ = z1;
  16470.             face->maxZ = z0;
  16471.         } else {
  16472.             face->minZ = z1;
  16473.             face->maxZ = z0;
  16474.         }
  16475.     } /* End of minZ/maxZ */
  16476.  
  16477.     return face;
  16478. }
  16479.  
  16480. /* b3dInitializePass2:
  16481.     Do a second initialization pass if the face is known to be visible.
  16482. */
  16483. int b3dInitializePass2(B3DPrimitiveFace *face)
  16484. {
  16485.     double majorDv, minorDv, baseValue;
  16486.     double dvdx, dvdy;
  16487.     B3DPrimitiveAttribute *attr;
  16488.     B3DPrimitiveVertex *v0 = face->v0;
  16489.     B3DPrimitiveVertex *v1 = face->v1;
  16490.     B3DPrimitiveVertex *v2 = face->v2;
  16491.  
  16492.     {
  16493.         int ok;
  16494.         b3dAllocAttrib(attrAlloc, face, ok);
  16495.         if(!!ok) return 0; /* NOT initalized */
  16496.     }
  16497.  
  16498.     attr = face->attributes;
  16499.     assert(attr);
  16500.     
  16501.     if(face->flags & B3D_FACE_RGB) {
  16502.         /* Setup RGB interpolation */
  16503.         majorDv = v2->redValue - v0->redValue;
  16504.         minorDv = v1->redValue - v0->redValue;
  16505.         dvdx = face->oneOverArea * ((majorDv * face->minorDy) - (minorDv * face->majorDy));
  16506.         dvdy = face->oneOverArea * ((minorDv * face->majorDx) - (majorDv * face->minorDx));
  16507.         attr->value = (float) v0->redValue;
  16508.         attr->dvdx  = (float) dvdx;
  16509.         attr->dvdy  = (float) dvdy;
  16510.         attr = attr->next;
  16511.  
  16512.         majorDv = v2->greenValue - v0->greenValue;
  16513.         minorDv = v1->greenValue - v0->greenValue;
  16514.         dvdx = face->oneOverArea * ((majorDv * face->minorDy) - (minorDv * face->majorDy));
  16515.         dvdy = face->oneOverArea * ((minorDv * face->majorDx) - (majorDv * face->minorDx));
  16516.         attr->value = (float) v0->greenValue;
  16517.         attr->dvdx  = (float) dvdx;
  16518.         attr->dvdy  = (float) dvdy;
  16519.         attr = attr->next;
  16520.  
  16521.         majorDv = v2->blueValue - v0->blueValue;
  16522.         minorDv = v1->blueValue - v0->blueValue;
  16523.         dvdx = face->oneOverArea * ((majorDv * face->minorDy) - (minorDv * face->majorDy));
  16524.         dvdy = face->oneOverArea * ((minorDv * face->majorDx) - (majorDv * face->minorDx));
  16525.         attr->value = (float) v0->blueValue;
  16526.         attr->dvdx  = (float) dvdx;
  16527.         attr->dvdy  = (float) dvdy;
  16528.         attr = attr->next;
  16529.     }
  16530.     if(face->flags & B3D_FACE_ALPHA) {
  16531.         /* Setup alpha interpolation */
  16532.         majorDv = v2->alphaValue - v0->alphaValue;
  16533.         minorDv = v1->alphaValue - v0->alphaValue;
  16534.         dvdx = face->oneOverArea * ((majorDv * face->minorDy) - (minorDv * face->majorDy));
  16535.         dvdy = face->oneOverArea * ((minorDv * face->majorDx) - (majorDv * face->minorDx));
  16536.         attr->value = (float) v0->alphaValue;
  16537.         attr->dvdx  = (float) dvdx;
  16538.         attr->dvdy  = (float) dvdy;
  16539.         attr = attr->next;
  16540.     }
  16541.     if(face->flags & B3D_FACE_STW) {
  16542.         /* Setup texture coordinate interpolation */
  16543.         double w0 = v0->rasterPosW;
  16544.         double w1 = v1->rasterPosW;
  16545.         double w2 = v2->rasterPosW;
  16546.  
  16547.         majorDv = w2 - w0;
  16548.         minorDv = w1 - w0;
  16549.         dvdx = face->oneOverArea * ((majorDv * face->minorDy) - (minorDv * face->majorDy));
  16550.         dvdy = face->oneOverArea * ((minorDv * face->majorDx) - (majorDv * face->minorDx));
  16551.         attr->value = (float) w0;
  16552.         attr->dvdx  = (float) dvdx;
  16553.         attr->dvdy  = (float) dvdy;
  16554.         attr = attr->next;
  16555.  
  16556.         baseValue = v0->texCoordS * w0;
  16557.         majorDv = (v2->texCoordS * w2) - baseValue;
  16558.         minorDv = (v1->texCoordS * w1) - baseValue;
  16559.         dvdx = face->oneOverArea * ((majorDv * face->minorDy) - (minorDv * face->majorDy));
  16560.         dvdy = face->oneOverArea * ((minorDv * face->majorDx) - (majorDv * face->minorDx));
  16561.         attr->value = (float) baseValue;
  16562.         attr->dvdx  = (float) dvdx;
  16563.         attr->dvdy  = (float) dvdy;
  16564.         attr = attr->next;
  16565.  
  16566.         baseValue = v0->texCoordT * w0;
  16567.         majorDv = (v2->texCoordT * w2) - baseValue;
  16568.         minorDv = (v1->texCoordT * w1) - baseValue;
  16569.         dvdx = face->oneOverArea * ((majorDv * face->minorDy) - (minorDv * face->majorDy));
  16570.         dvdy = face->oneOverArea * ((minorDv * face->majorDx) - (majorDv * face->minorDx));
  16571.         attr->value = (float) baseValue;
  16572.         attr->dvdx  = (float) dvdx;
  16573.         attr->dvdy  = (float) dvdy;
  16574.         attr = attr->next;
  16575.     }
  16576.     face->flags |= B3D_FACE_INITIALIZED;
  16577.     return 1;
  16578. }
  16579.  
  16580. /* b3dInitializeEdge:
  16581.     Initialize the incremental values of the given edge.
  16582. */
  16583. /* INLINE b3dInitializeEdge(edge) */
  16584. void b3dInitializeEdge(B3DPrimitiveEdge *edge)
  16585. {
  16586.     assert(edge);
  16587.     assert(edge->nLines);
  16588.     edge->xValue = edge->v0->windowPosX;
  16589.     edge->zValue = edge->v0->rasterPosZ;
  16590.     if(edge->nLines > 1) {
  16591.         edge->xIncrement = (edge->v1->windowPosX - edge->v0->windowPosX) / edge->nLines;
  16592.         edge->zIncrement = (edge->v1->rasterPosZ - edge->v0->rasterPosZ) / (float) edge->nLines;
  16593.     } else {
  16594.         edge->xIncrement = (edge->v1->windowPosX - edge->v0->windowPosX);
  16595.         edge->zIncrement = (edge->v1->rasterPosZ - edge->v0->rasterPosZ);
  16596.     }
  16597. }
  16598. /* --INLINE-- */
  16599.  
  16600.  
  16601. /*************************************************************/
  16602. /*************************************************************/
  16603. /*************************************************************/
  16604.  
  16605. /* b3dFirstIndexForInserting:
  16606.     Return the first possible index for inserting an edge with the given x value.
  16607. */
  16608.  
  16609. int b3dFirstIndexForInserting(B3DPrimitiveEdgeList *list, int xValue)
  16610. {
  16611.     int low, high, index;
  16612.     low = 0;
  16613.     high = list->size-1;
  16614.     while(low <= high) {
  16615.         index = (low + high) >> 1;
  16616.         if(list->data[index]->xValue <= xValue)
  16617.             low = index+1;
  16618.         else
  16619.             high = index-1;
  16620.     }
  16621.     index = low;
  16622.     while(index > 0 && (list->data[index-1]->xValue) == xValue)
  16623.         index--;
  16624.     return index;
  16625. }
  16626.  
  16627. /* b3dAddEdgeBeforeIndex:
  16628.     Insert the edge to the list before the given index.
  16629. */
  16630. /* INLINE b3dAddEdgeBeforeIndex(list, edge, index) */
  16631. void b3dAddEdgeBeforeIndex(B3DPrimitiveEdgeList *list, B3DPrimitiveEdge *edge, int index)
  16632. {
  16633.     int i;
  16634.  
  16635.     if(b3dDebug)
  16636.         if(list->size == list->max)
  16637.             b3dAbort("No more space for adding edges");
  16638.  
  16639.     assert( (list->size == index) || (list->data[index]->xValue >= edge->xValue));
  16640.     for(i=list->size-1; i >= index; i--)
  16641.         list->data[i+1] = list->data[i];
  16642.     list->data[index] = edge;
  16643.     list->size++;
  16644. }
  16645. /* --INLINE-- */
  16646.  
  16647. /* b3d2AddEdgesBeforeIndex:
  16648.     Insert the two edge to the list before the given index.
  16649. */
  16650. /* INLINE b3dAdd2EdgesBeforeIndex(list, edge1, edge2, index) */
  16651. void b3dAdd2EdgesBeforeIndex(B3DPrimitiveEdgeList *list, 
  16652.                              B3DPrimitiveEdge *edge1, 
  16653.                              B3DPrimitiveEdge *edge2, 
  16654.                              int index)
  16655. {
  16656.     int i;
  16657.  
  16658.     if(b3dDebug)
  16659.         if(list->size+1 >= list->max)
  16660.             b3dAbort("No more space for adding edges");
  16661.  
  16662.     assert( edge1->xValue == edge2->xValue);
  16663.     assert( (list->size == index) || (list->data[index]->xValue >= edge1->xValue));
  16664.  
  16665.     for(i=list->size-1; i >= index; i--)
  16666.         list->data[i+2] = list->data[i];
  16667.     list->data[index] = edge1;
  16668.     list->data[index+1] = edge2;
  16669.     list->size += 2;
  16670. }
  16671. /* --INLINE-- */
  16672.  
  16673. /* b3dAdjustFaceEdges:
  16674.     Assign left and right edges to the given face.
  16675. */
  16676. /* INLINE b3dAdjustFaceEdges(face, edge1, edge2) */
  16677. void b3dAdjustFaceEdges(B3DPrimitiveFace *face, B3DPrimitiveEdge *edge1, B3DPrimitiveEdge *edge2)
  16678. {
  16679.     assert(face);
  16680.     assert(edge1);
  16681.     assert(edge2);
  16682.     if(edge1->xValue == edge2->xValue) {
  16683.         if(edge1->xIncrement <= edge2->xIncrement) {
  16684.             face->leftEdge = edge1;
  16685.             face->rightEdge = edge2;
  16686.         } else {
  16687.             face->leftEdge = edge2;
  16688.             face->rightEdge = edge1;
  16689.         }
  16690.     } else {
  16691.         if(edge1->xValue <= edge2->xValue) {
  16692.             face->leftEdge = edge1;
  16693.             face->rightEdge = edge2;
  16694.         } else {
  16695.             face->leftEdge = edge2;
  16696.             face->rightEdge = edge1;
  16697.         }
  16698.     }
  16699. }
  16700. /* --INLINE-- */
  16701.  
  16702. /* b3dAddLowerEdgeFromFace:
  16703.     Add a new lower edge from the given face.
  16704.     NOTE: oldEdge may be NULL!!
  16705.     NOTE: May cause allocation of one edge!!
  16706. */
  16707. B3DPrimitiveEdge *b3dAddLowerEdgeFromFace(B3DPrimitiveFace *face, B3DPrimitiveEdge *oldEdge)
  16708. {
  16709.     B3DPrimitiveVertex *v0 = face->v0;
  16710.     B3DPrimitiveVertex *v1 = face->v1;
  16711.     B3DPrimitiveVertex *v2 = face->v2;
  16712.     int xValue = v1->windowPosX;
  16713.     int index;
  16714.  
  16715.     /* Search the list of added edges to merge the edges from the face */
  16716.     index = b3dFirstIndexForInserting(addedEdges, xValue);
  16717.     for(;index<addedEdges->size; index++) {
  16718.         B3DPrimitiveEdge *edge = addedEdges->data[index];
  16719.         if(edge->xValue !!= xValue) break;
  16720.         if(edge->rightFace) continue;
  16721.         if((edge->v0 == v1 && edge->v1 == v2) || /* The simple test*/
  16722.             /* The complex test */
  16723.             (edge->v0->windowPosX == v1->windowPosX &&
  16724.              edge->v0->windowPosY == v1->windowPosY &&
  16725.              edge->v0->rasterPosZ == v1->rasterPosZ &&
  16726.              edge->v1->windowPosX == v2->windowPosX &&
  16727.              edge->v1->windowPosY == v2->windowPosY &&
  16728.              edge->v1->rasterPosZ == v2->rasterPosZ)) {
  16729.             /* Found the edge */
  16730.             if(face->leftEdge == oldEdge)
  16731.                 face->leftEdge = edge;
  16732.             else
  16733.                 face->rightEdge = edge;
  16734.             edge->rightFace = face;
  16735.             return edge;
  16736.         }
  16737.     }
  16738.     /* Need to create a new edge.
  16739.        NOTE: Index already points to the right insertion point.
  16740.     */
  16741.     {
  16742.         B3DPrimitiveEdge *minorEdge;
  16743.         int nLines = (v2->windowPosY >> B3D_FixedToIntShift) - (v1->windowPosY >> B3D_FixedToIntShift);
  16744.         if(!!nLines) return NULL; /* Edge is horizontal */
  16745.         b3dAllocEdge(edgeAlloc, minorEdge);
  16746.  
  16747.         if(b3dDebug)
  16748.             if(!!minorEdge)
  16749.                 b3dAbort("Edge allocation failed");
  16750.  
  16751.         minorEdge->v0 = v1;
  16752.         minorEdge->v1 = v2;
  16753.         minorEdge->nLines = nLines;
  16754.         minorEdge->leftFace = face;
  16755.         minorEdge->rightFace = NULL;
  16756.         if(face->leftEdge == oldEdge)
  16757.             face->leftEdge = minorEdge;
  16758.         else
  16759.             face->rightEdge = minorEdge;
  16760.         b3dInitializeEdge(minorEdge);
  16761.         b3dAddEdgeBeforeIndex(addedEdges, minorEdge, index);
  16762.         return minorEdge;
  16763.     }
  16764.     /* NOT REACHED */
  16765. }
  16766.  
  16767. /* b3dAddEdgesFromFace:
  16768.     Add the two new edges from the given primitive face.
  16769.     NOTE: May cause allocation of two edges (but not three)!!
  16770. */
  16771. void b3dAddEdgesFromFace(B3DPrimitiveFace *face, int yValue)
  16772. {
  16773.     int needMajor = 1;
  16774.     int needMinor = 1;
  16775.     B3DPrimitiveEdge *majorEdge = NULL;
  16776.     B3DPrimitiveEdge *minorEdge = NULL;
  16777.     B3DPrimitiveVertex *v0 = face->v0;
  16778.     B3DPrimitiveVertex *v1 = face->v1;
  16779.     B3DPrimitiveVertex *v2 = face->v2;
  16780.     int xValue = v0->windowPosX;
  16781.     int index;
  16782.  
  16783.     /* Search the list of added edges to merge the edges from the face */
  16784.     index = b3dFirstIndexForInserting(addedEdges, xValue);
  16785.     for(;index<addedEdges->size; index++) {
  16786.         B3DPrimitiveEdge *edge = addedEdges->data[index];
  16787.         if(edge->xValue !!= xValue) break;
  16788.         if(edge->rightFace) continue;
  16789.         if(edge->v0 !!= v0 &&
  16790.             (edge->v0->windowPosY !!= v0->windowPosY ||
  16791.              edge->v0->rasterPosZ !!= v0->rasterPosZ)) continue;
  16792.         /* If we come to this point the edge might be usable for merging the face */
  16793.         if(needMajor && /* Test only if major edge is needed */
  16794.             (edge->v1 == v2 || /* Simple test */
  16795.             /* A more complex test */
  16796.             (edge->v1->windowPosX == v2->windowPosX &&
  16797.              edge->v1->windowPosY == v2->windowPosY &&
  16798.              edge->v1->rasterPosZ == v2->rasterPosZ))) {
  16799.             /* Yepp. That''s the new major */
  16800.             majorEdge = edge;
  16801.             majorEdge->rightFace = face;
  16802.             majorEdge->flags  |= B3D_EDGE_RIGHT_MAJOR;
  16803.             
  16804.             if(b3dDoStats) nFaces++;
  16805.  
  16806.             if(!!needMinor) {
  16807.                 b3dAdjustFaceEdges(face, majorEdge, minorEdge);
  16808.                 return; /* done */
  16809.             }
  16810.             needMajor = 0;
  16811.         } else if(needMinor && /* Test only if minor edge is needed */
  16812.             (edge->v1 == v1 || /* Simple test */
  16813.             /* A more complex test */
  16814.             (edge->v1->windowPosX == v1->windowPosX &&
  16815.              edge->v1->windowPosY == v1->windowPosY &&
  16816.              edge->v1->rasterPosZ == v1->rasterPosZ))) {
  16817.             /* Yepp. That''s the new minor */
  16818.             minorEdge = edge;
  16819.             minorEdge->rightFace = face;
  16820.             minorEdge->flags |= B3D_EDGE_CONTINUE_RIGHT;
  16821.             if(!!needMajor) {
  16822.                 b3dAdjustFaceEdges(face, majorEdge, minorEdge);
  16823.                 return; /* done */
  16824.             }
  16825.             needMinor = 0;
  16826.         }
  16827.     }
  16828.     /*  Need to create new edges.
  16829.         Note: index already points to the right insertion point in addedEdges 
  16830.     */
  16831.     if(needMajor) {
  16832.         int nLines = (v2->windowPosY >> B3D_FixedToIntShift) - (v0->windowPosY >> B3D_FixedToIntShift);
  16833.  
  16834.         if(!!nLines) {
  16835.             /* The major edge is horizontal. */
  16836.             b3dFreeFace(faceAlloc, face);
  16837.             return;
  16838.         }
  16839.         b3dAllocEdge(edgeAlloc, majorEdge);
  16840.         if(b3dDebug)
  16841.             if(!!majorEdge) b3dAbort("Edge allocation failed");
  16842.         majorEdge->v0 = v0;
  16843.         majorEdge->v1 = v2;
  16844.         majorEdge->nLines = nLines;
  16845.         majorEdge->leftFace = face;
  16846.         majorEdge->rightFace = NULL;
  16847.         majorEdge->flags  |= B3D_EDGE_LEFT_MAJOR;
  16848.         b3dInitializeEdge(majorEdge);
  16849.         if(b3dDoStats) nFaces++;
  16850.     }
  16851.  
  16852.     if(needMinor) {
  16853.         int nLines = (v1->windowPosY >> B3D_FixedToIntShift) - (v0->windowPosY >> B3D_FixedToIntShift);
  16854.  
  16855.         if(!!nLines) {
  16856.             /* Note: If the (upper) minor edge is horizontal, use the lower one.
  16857.                Note: The lower edge cannot be horizontal if the major edge isn''t
  16858.             */
  16859.             if(needMajor) {
  16860.                 b3dAddEdgeBeforeIndex(addedEdges, majorEdge, index);
  16861.             }
  16862.             minorEdge = b3dAddLowerEdgeFromFace(face,NULL);
  16863.  
  16864.             if(b3dDebug)
  16865.                 if(!!minorEdge || minorEdge->nLines == 0)
  16866.                     b3dAbort("minor edge is horizontal");
  16867.  
  16868.             b3dAdjustFaceEdges(face, majorEdge, minorEdge);
  16869.             return;
  16870.         }
  16871.  
  16872.         b3dAllocEdge(edgeAlloc, minorEdge);
  16873.  
  16874.         if(b3dDebug)
  16875.             if(!!minorEdge) b3dAbort("Edge allocation failed");
  16876.  
  16877.         minorEdge->v0 = v0;
  16878.         minorEdge->v1 = v1;
  16879.         minorEdge->nLines = nLines;
  16880.         minorEdge->leftFace = face;
  16881.         minorEdge->rightFace = NULL;
  16882.         minorEdge->flags  |= B3D_EDGE_CONTINUE_LEFT;
  16883.         b3dInitializeEdge(minorEdge);
  16884.     }
  16885.  
  16886.     /* Add the newly created edges to addedEdges */
  16887.     if(needMinor && needMajor) {
  16888.         b3dAdd2EdgesBeforeIndex(addedEdges, majorEdge, minorEdge, index);
  16889.     } else if(needMajor) {
  16890.         b3dAddEdgeBeforeIndex(addedEdges, majorEdge, index);
  16891.     } else {
  16892.         b3dAddEdgeBeforeIndex(addedEdges, minorEdge, index);
  16893.     }
  16894.     b3dAdjustFaceEdges(face, majorEdge, minorEdge);
  16895. }
  16896.  
  16897.  
  16898. /* b3dRemoveAETEdge:
  16899.     Remove the given edge from the AET.
  16900.     NOTE: May cause allocation of two edges!!
  16901. */
  16902. /* INLINE b3dRemoveAETEdge(aet, edge, yValue, aetPos) */
  16903. void b3dRemoveAETEdge(B3DActiveEdgeTable *aet, B3DPrimitiveEdge *edge, int yValue, int aetPos)
  16904. {
  16905.     /* Remove edge and add lower edges if necessary */
  16906.     int j;
  16907.     B3DPrimitiveEdge **aetData = aet->data;
  16908.  
  16909.     assert(aetData[aetPos] == edge);
  16910.  
  16911.     if(b3dDebug)
  16912.         if( (edge->v1->windowPosY >> B3D_FixedToIntShift) !!= yValue )
  16913.             b3dAbort("Edge exceeds range");
  16914.  
  16915.     /* Remove the edge and adjust the stuff */
  16916.     for(j=aetPos+1; j < aet->size; j++) aetData[j-1] = aetData[j];
  16917.     aet->size--;
  16918.     /* Add new lower edges */
  16919.     if(edge->flags & B3D_EDGE_CONTINUE_LEFT) {
  16920.         b3dAddLowerEdgeFromFace(edge->leftFace, edge);
  16921.     }
  16922.     if(edge->flags & B3D_EDGE_CONTINUE_RIGHT) {
  16923.         b3dAddLowerEdgeFromFace(edge->rightFace, edge);
  16924.     }
  16925.     if(edge->flags & B3D_EDGE_LEFT_MAJOR) {
  16926.         /* Free left face */
  16927.         b3dFreeAttrib(attrAlloc, edge->leftFace);
  16928.         b3dFreeFace(faceAlloc, edge->leftFace);
  16929.         if(b3dDoStats) nFaces--;
  16930.     }
  16931.     if(edge->flags & B3D_EDGE_RIGHT_MAJOR) {
  16932.         /* Free right face */
  16933.         b3dFreeAttrib(attrAlloc, edge->rightFace);
  16934.         b3dFreeFace(faceAlloc, edge->rightFace);
  16935.         if(b3dDoStats) nFaces--;
  16936.     }
  16937.     /* And free old edge */
  16938.     b3dFreeEdge(edgeAlloc, edge);
  16939. }
  16940. /* --INLINE-- */
  16941.  
  16942. /* b3dMergeAETEdgesFrom:
  16943.     Merge the edges from the given source into the AET.
  16944. */
  16945. void b3dMergeAETEdgesFrom(B3DActiveEdgeTable *aet, B3DPrimitiveEdgeList *src)
  16946. {
  16947.     int srcIndex, aetIndex, outIndex, i;
  16948.     B3DPrimitiveEdge *srcEdge, *aetEdge;
  16949.  
  16950.     assert(aet);
  16951.     assert(src);
  16952.     assert(src->size);
  16953.     assert(aet->size + src->size <= aet->max);
  16954.  
  16955.     if(!!aet->size) {
  16956.         for(i=0; i<src->size; i++) aet->data[i] = src->data[i];
  16957.         aet->size += src->size;
  16958.         return;
  16959.     }
  16960.  
  16961.     /* Merge the input by stepping backwards through the aet and checking each edge */
  16962.     outIndex = aet->size + src->size - 1;
  16963.     srcIndex = src->size-1;
  16964.     aetIndex = aet->size-1;
  16965.     srcEdge = src->data[srcIndex];
  16966.     aetEdge = aet->data[aetIndex];
  16967.     aet->size += src->size;
  16968.     while(1) {
  16969.         if(srcEdge->xValue >= aetEdge->xValue) {
  16970.             /* output srcEdge */
  16971.             aet->data[outIndex--] = srcEdge;
  16972.             if(!!srcIndex--) return;
  16973.             srcEdge = src->data[srcIndex];
  16974.         } else {
  16975.             /* output aetEdge */
  16976.             aet->data[outIndex--] = aetEdge;
  16977.             if(!!aetIndex--) {
  16978.                 for(i=0; i <= srcIndex; i++) aet->data[i] = src->data[i];
  16979.                 return;
  16980.             }
  16981.             aetEdge = aet->data[aetIndex];
  16982.         }
  16983.     }
  16984. }
  16985.  
  16986. /* INLINE b3dAdvanceAETEdge(edge, aetData, aetStart) */
  16987. void b3dAdvanceAETEdge(B3DPrimitiveEdge *edge,
  16988.                     B3DPrimitiveEdge **aetData,
  16989.                     int aetStart)
  16990. {
  16991.     /* Advance to next scan line */
  16992.     edge->zValue += edge->zIncrement;
  16993.     edge->xValue += edge->xIncrement;
  16994.     /* Check if AET sort order is okay */
  16995.     if(aetStart && aetData[aetStart-1]->xValue > edge->xValue) {
  16996.         /* Must resort rightEdge */
  16997.         int xValue = edge->xValue;
  16998.         int j = aetStart;
  16999.         /* Move the edge left */
  17000.         while(j>0 && aetData[j-1]->xValue > xValue) {
  17001.             aetData[j] = aetData[j-1];
  17002.             j--;
  17003.         }
  17004.         aetData[j] = edge;
  17005.     }
  17006. }
  17007. /* --INLINE-- */
  17008.  
  17009. /*************************************************************/
  17010. /*************************************************************/
  17011. /*************************************************************/
  17012. #ifdef DEBUG
  17013. double zValueAt(B3DPrimitiveFace *face, double xValue, double yValue)
  17014. {
  17015.     return 
  17016.         (face->v0->rasterPosZ +
  17017.             (((double)xValue - face->v0->rasterPosX) * face->dzdx) +
  17018.             (((double)yValue - face->v0->rasterPosY) * face->dzdy));
  17019. }
  17020. #else
  17021. #define zValueAt(face, xValue, yValue) \
  17022.         ((face)->v0->rasterPosZ + \
  17023.             (((double)(xValue) - (face)->v0->rasterPosX) * (face)->dzdx) +\
  17024.             (((double)(yValue) - (face)->v0->rasterPosY) * (face)->dzdy))
  17025. #endif
  17026.  
  17027. /*************************************************************/
  17028. /*************************************************************/
  17029. /*************************************************************/
  17030.  
  17031. int b3dComputeIntersection(B3DPrimitiveFace *frontFace, 
  17032.                            B3DPrimitiveFace *backFace, 
  17033.                            int yValue, 
  17034.                            int errorValue)
  17035. {
  17036.     double dx1 = frontFace->rightEdge->xValue - frontFace->leftEdge->xValue;
  17037.     double dz1 = frontFace->rightEdge->zValue - frontFace->leftEdge->zValue;
  17038.     double dx2 = backFace->rightEdge->xValue - backFace->leftEdge->xValue;
  17039.     double dz2 = backFace->rightEdge->zValue - backFace->leftEdge->zValue;
  17040.     double px = backFace->leftEdge->xValue - frontFace->leftEdge->xValue;
  17041.     double pz = backFace->leftEdge->zValue - frontFace->leftEdge->zValue;
  17042.     double det = (dx1 * dz2) - (dx2 * dz1);
  17043.     if(det == 0.0) return errorValue;
  17044.     { 
  17045.         double det2 = ((px * dz2) - (pz * dx2)) / det;
  17046.         return frontFace->leftEdge->xValue + (int)(dx1 * det2);
  17047.     }
  17048.     /* not reached */
  17049. }
  17050.  
  17051. /* b3dCheckIntersectionOfFaces:
  17052.     Compute the possible intersection of frontFace and backFace.
  17053.     Store the result in nextIntersection if it is before any other
  17054.     intersection. Return true if other intersections tests should
  17055.     be performed, false otherwise.
  17056. */
  17057. int b3dCheckIntersectionOfFaces(B3DPrimitiveFace *frontFace,
  17058.                                  B3DPrimitiveFace *backFace,
  17059.                                  int yValue,
  17060.                                  B3DPrimitiveEdge *leftEdge,
  17061.                                  B3DPrimitiveEdge *nextIntersection)
  17062. {
  17063.     double frontZ, backZ;
  17064.     int xValue, rightX;
  17065.  
  17066.     /* Check if the backFace is completely behind the front face */
  17067.     if(backFace->minZ >= frontFace->maxZ) return 0; /* abort */
  17068.  
  17069.     /* Check if front and back face share any edges */
  17070.     if(frontFace->leftEdge == backFace->leftEdge) return 1; /* proceed */
  17071.     if(frontFace->rightEdge == backFace->rightEdge) return 1; /* proceed */
  17072.  
  17073.     /* Check if either front or back face are less than 1 pixel wide */
  17074.     if( (frontFace->leftEdge->xValue >> B3D_FixedToIntShift) ==
  17075.         (frontFace->rightEdge->xValue >> B3D_FixedToIntShift)) return 0; /* abort */
  17076.     if( (backFace->leftEdge->xValue >> B3D_FixedToIntShift) ==
  17077.         (backFace->rightEdge->xValue >> B3D_FixedToIntShift)) return 1; /* proceed */
  17078.  
  17079.     /* Choose the right x value of either front or back face,
  17080.         whichever is less (this is so we sample inside both faces) */
  17081.     if(frontFace->rightEdge->xValue <= backFace->rightEdge->xValue) {
  17082.         rightX = frontFace->rightEdge->xValue;
  17083.         frontZ = frontFace->rightEdge->zValue;
  17084.         backZ = zValueAt(backFace, rightX * B3D_FixedToFloat, yValue);
  17085.     } else {
  17086.         rightX = backFace->rightEdge->xValue;
  17087.         backZ = backFace->rightEdge->zValue;
  17088.         frontZ = zValueAt(frontFace, rightX * B3D_FixedToFloat, yValue);
  17089.     }
  17090.  
  17091.     if(backZ < frontZ) {
  17092.         /* possible intersection found */
  17093.         xValue = b3dComputeIntersection(frontFace, backFace, yValue, leftEdge->xValue);
  17094.         if(xValue > rightX) xValue = rightX;
  17095.         /* Ignore intersections at or before the leftEdge''s x value. Important. */
  17096.         if((xValue >> B3D_FixedToIntShift) <= (leftEdge->xValue >> B3D_FixedToIntShift))
  17097.             xValue = ((leftEdge->xValue >> B3D_FixedToIntShift) + 1) << B3D_IntToFixedShift;
  17098.         if(xValue < nextIntersection->xValue) {
  17099.             nextIntersection->xValue = xValue;
  17100.             nextIntersection->leftFace = frontFace;
  17101.             nextIntersection->rightFace = backFace;
  17102.         }
  17103.     }
  17104.     return 1;
  17105. }
  17106.  
  17107. /* b3dAdjustIntersections:
  17108.     Compute the possible intersections of the current front face
  17109.     with all active faces. Store the next intersection if any.
  17110. */
  17111. /* INLINE b3dAdjustIntersections(fillList, yValue, topEdge, nextIntersection) */
  17112. void b3dAdjustIntersections(B3DFillList *fillList,
  17113.                             int yValue,
  17114.                             B3DPrimitiveEdge *topEdge,
  17115.                             B3DPrimitiveEdge *nextIntersection)
  17116. {
  17117.     B3DPrimitiveFace *frontFace = fillList->firstFace;
  17118.     if(frontFace) {
  17119.         B3DPrimitiveFace *backFace = frontFace->nextFace;
  17120.         int proceed = 1;
  17121.         while(backFace && proceed) {
  17122.             proceed = b3dCheckIntersectionOfFaces(frontFace, backFace, yValue, topEdge, nextIntersection);
  17123.             backFace = backFace->nextFace;
  17124.         }
  17125.     }
  17126. }
  17127. /* --INLINE-- */
  17128.  
  17129. /*************************************************************/
  17130. /*************************************************************/
  17131. /*************************************************************/
  17132.  
  17133. void b3dValidateFillList(B3DFillList *list)
  17134. {
  17135.     B3DPrimitiveFace *firstFace = list->firstFace;
  17136.     B3DPrimitiveFace *lastFace = list->lastFace;
  17137.     B3DPrimitiveFace *face;
  17138.  
  17139.     if(!!firstFace && !!lastFace) return;
  17140.     if(firstFace->prevFace)
  17141.         b3dAbort("Bad fill list");
  17142.     if(lastFace->nextFace)
  17143.         b3dAbort("Bad fill list");
  17144.     face = firstFace;
  17145.     while(face !!= lastFace)
  17146.         face = face->nextFace;
  17147.     /* Validate sort order */
  17148.     if(firstFace == lastFace)
  17149.         return; /* 0 or 1 element */
  17150.     face = firstFace->nextFace;
  17151.     while(face->nextFace) {
  17152.         if(face->minZ > face->nextFace->minZ)
  17153.             b3dAbort("Fill list sorting problem");
  17154.         face = face->nextFace;
  17155.     }
  17156. }
  17157.  
  17158. /* INLINE b3dAddFirstFill(fillList, aFace) */
  17159. void b3dAddFirstFill(B3DFillList *fillList, B3DPrimitiveFace *aFace)
  17160. {
  17161.     B3DPrimitiveFace *firstFace = fillList->firstFace;
  17162.     if(firstFace)
  17163.         firstFace->prevFace = aFace;
  17164.     else
  17165.         fillList->lastFace = aFace;
  17166.     aFace->nextFace = firstFace;
  17167.     aFace->prevFace = NULL;
  17168.     fillList->firstFace = aFace;
  17169.     if(b3dDebug) b3dValidateFillList(fillList);
  17170. }
  17171. /* --INLINE-- */
  17172.  
  17173. /* INLINE b3dAddLastFill(fillList, aFace) */
  17174. void b3dAddLastFill(B3DFillList *fillList, B3DPrimitiveFace *aFace)
  17175. {
  17176.     B3DPrimitiveFace *lastFace = fillList->lastFace;
  17177.     if(lastFace)
  17178.         lastFace->nextFace = aFace;
  17179.     else
  17180.         fillList->firstFace = aFace;
  17181.     aFace->prevFace = lastFace;
  17182.     aFace->nextFace = NULL;
  17183.     fillList->lastFace = aFace;
  17184.     if(b3dDebug) b3dValidateFillList(fillList);
  17185. }
  17186. /* --INLINE-- */
  17187.  
  17188. /* INLINE b3dRemoveFill(fillList, aFace) */
  17189. void b3dRemoveFill(B3DFillList *fillList, B3DPrimitiveFace *aFace)
  17190. {
  17191.     if(b3dDebug) b3dValidateFillList(fillList);
  17192.     if(aFace->prevFace)
  17193.         aFace->prevFace->nextFace = aFace->nextFace;
  17194.     else
  17195.         fillList->firstFace = aFace->nextFace;
  17196.     if(aFace->nextFace)
  17197.         aFace->nextFace->prevFace = aFace->prevFace;
  17198.     else
  17199.         fillList->lastFace = aFace->prevFace;
  17200. }
  17201. /* --INLINE-- */
  17202.  
  17203. /* INLINE b3dInsertBeforeFill(fillList, aFace, otherFace) */
  17204. void b3dInsertBeforeFill(B3DFillList *fillList, B3DPrimitiveFace *aFace, B3DPrimitiveFace *otherFace)
  17205. {
  17206.     assert(otherFace !!= fillList->firstFace);
  17207.  
  17208.     aFace->nextFace = otherFace;
  17209.     aFace->prevFace = otherFace->prevFace;
  17210.     aFace->prevFace->nextFace = aFace;
  17211.     otherFace->prevFace = aFace;
  17212.     if(b3dDebug) b3dValidateFillList(fillList);
  17213. }
  17214. /* --INLINE-- */
  17215.  
  17216. /* INLINE b3dAddFrontFill(fillList, aFace) */
  17217. void b3dAddFrontFill(B3DFillList *fillList, B3DPrimitiveFace *aFace)
  17218. {
  17219.     B3DPrimitiveFace *firstFace = fillList->firstFace;
  17220.     if(firstFace !!= fillList->lastFace) {
  17221.         /* Meaning that we must find the new position for the old front face */
  17222.         B3DPrimitiveFace *backFace = firstFace->nextFace;
  17223.         float minZ = firstFace->minZ;
  17224.  
  17225.         while(backFace && backFace->minZ < minZ)
  17226.             backFace = backFace->nextFace;
  17227.  
  17228.         /* Insert firstFace before backFace */
  17229.         if(firstFace->nextFace !!= backFace) {
  17230.             B3DPrimitiveFace *tempFace = firstFace;
  17231.  
  17232.             b3dRemoveFill(fillList, tempFace);
  17233.             if(backFace) {
  17234.                 b3dInsertBeforeFill(fillList, tempFace, backFace);
  17235.             } else {
  17236.                 b3dAddLastFill(fillList, tempFace);
  17237.             }
  17238.         }
  17239.     }
  17240.     b3dAddFirstFill(fillList, aFace);
  17241.     if(b3dDebug) b3dValidateFillList(fillList);
  17242. }
  17243. /* --INLINE-- */
  17244.  
  17245. /* INLINE b3dAddBackFill(fillList, aFace) */
  17246. void b3dAddBackFill(B3DFillList *fillList, B3DPrimitiveFace *aFace)
  17247. {
  17248.     B3DPrimitiveFace *firstFace = fillList->firstFace;
  17249.     B3DPrimitiveFace *lastFace = fillList->lastFace;
  17250.     B3DPrimitiveFace *face;
  17251.     float minZ = aFace->minZ;
  17252.  
  17253.     assert(firstFace);
  17254.  
  17255.     if(firstFace == lastFace || minZ >= lastFace->minZ) {
  17256.         b3dAddLastFill(fillList, aFace);
  17257.     } else {
  17258.         /* Try an estimation on how to search */
  17259.         if(minZ <= (firstFace->minZ + lastFace->minZ) * 0.5) {
  17260.             /* search front to back */
  17261.             face = firstFace->nextFace;
  17262.             while(face->minZ < minZ) face = face->nextFace;
  17263.         } else {
  17264.             /* search back to front */
  17265.             face = lastFace->prevFace; /* already checked if lastFace->minZ <= minZ */
  17266.             while(face->minZ > minZ) face = face->prevFace;
  17267.             face = face->nextFace;
  17268.         }
  17269.         b3dInsertBeforeFill(fillList, aFace, face);
  17270.     }
  17271.     if(b3dDebug) b3dValidateFillList(fillList);
  17272. }
  17273. /* --INLINE-- */
  17274.  
  17275. /* INLINE b3dCleanupFill(fillList) */
  17276. void b3dCleanupFill(B3DFillList *fillList)
  17277. {
  17278.     B3DPrimitiveFace *firstFace = fillList->firstFace;
  17279.  
  17280.     while(firstFace) {
  17281.         firstFace->flags ^= B3D_FACE_ACTIVE;
  17282.         firstFace = firstFace->nextFace;
  17283.     }
  17284.     fillList->firstFace = fillList->lastFace = NULL;
  17285. }
  17286. /* --INLINE-- */
  17287.  
  17288. void b3dSearchForNewTopFill(B3DFillList *fillList, int scaledX, int yValue)
  17289. {
  17290.     B3DPrimitiveFace *topFace = fillList->firstFace;
  17291.  
  17292.     if(b3dDebug) b3dValidateFillList(fillList);
  17293.     if(topFace) { /* only if there is any */
  17294.         B3DPrimitiveFace *face = topFace->nextFace;
  17295.         double xValue = scaledX * B3D_FixedToFloat;
  17296.         double topZ = zValueAt(topFace, xValue, yValue);
  17297.  
  17298.         /* Note: since the list is ordered we need only to search until face->minZ >= topZ */
  17299.         while(face && face->minZ <= topZ) {
  17300.             double faceZ = zValueAt(face, xValue, yValue);
  17301.             if(faceZ < topZ) {
  17302.                 topZ = faceZ;
  17303.                 topFace = face;
  17304.             }
  17305.             face = face->nextFace;
  17306.         }
  17307.         /* and move the guy to front */
  17308.         b3dRemoveFill(fillList, topFace);
  17309.         b3dAddFrontFill(fillList, topFace);
  17310.     }
  17311. }
  17312.  
  17313. /* INLINE b3dToggleTopFills(fillList, edge, yValue) */
  17314. void b3dToggleTopFills(B3DFillList *fillList, B3DPrimitiveEdge *edge, int yValue)
  17315. {
  17316.     B3DPrimitiveFace *leftFace = edge->leftFace;
  17317.     B3DPrimitiveFace *rightFace = edge->rightFace;
  17318.     if(b3dDebug) b3dValidateFillList(fillList);
  17319.     assert(leftFace !!= rightFace);
  17320.     if(rightFace) {
  17321.         int xorMask = leftFace->flags ^ rightFace->flags;
  17322.         if(xorMask & B3D_FACE_ACTIVE) {
  17323.             if(leftFace->flags & B3D_FACE_ACTIVE) {
  17324.                 b3dRemoveFill(fillList, leftFace);
  17325.                 b3dAddFrontFill(fillList, rightFace);
  17326.             } else {
  17327.                 b3dRemoveFill(fillList, rightFace);
  17328.                 b3dAddFrontFill(fillList, leftFace);
  17329.             }
  17330.         } else {
  17331.             if(leftFace->flags & B3D_FACE_ACTIVE) {
  17332.                 b3dRemoveFill(fillList, leftFace);
  17333.                 b3dRemoveFill(fillList, rightFace);
  17334.                 b3dSearchForNewTopFill(fillList, edge->xValue, yValue);
  17335.             } else {
  17336.                 if(leftFace->dzdx <= rightFace->dzdx) {
  17337.                     b3dAddFrontFill(fillList, leftFace);
  17338.                     b3dAddBackFill(fillList, rightFace);
  17339.                 } else {
  17340.                     b3dAddFrontFill(fillList, rightFace);
  17341.                     b3dAddBackFill(fillList, leftFace);
  17342.                 }
  17343.             }
  17344.         }
  17345.         leftFace->flags ^= B3D_FACE_ACTIVE;
  17346.         rightFace->flags ^= B3D_FACE_ACTIVE;
  17347.     } else {
  17348.         if(leftFace->flags & B3D_FACE_ACTIVE) {
  17349.             b3dRemoveFill(fillList, leftFace);
  17350.             b3dSearchForNewTopFill(fillList, edge->xValue, yValue);
  17351.         } else {
  17352.             b3dAddFrontFill(fillList, leftFace);
  17353.         }
  17354.         leftFace->flags ^= B3D_FACE_ACTIVE;
  17355.     }
  17356.     if(b3dDebug) b3dValidateFillList(fillList);
  17357. }
  17358. /* --INLINE-- */
  17359.  
  17360. /* INLINE b3dToggleBackFills(fillList, edge, yValue, nextIntersection) */
  17361. void b3dToggleBackFills(B3DFillList *fillList, 
  17362.                         B3DPrimitiveEdge *edge, 
  17363.                         int yValue,
  17364.                         B3DPrimitiveEdge *nextIntersection)
  17365. {
  17366.     B3DPrimitiveFace *face = edge->leftFace;
  17367.     if(b3dDebug) b3dValidateFillList(fillList);
  17368.     if(face->flags & B3D_FACE_ACTIVE) {
  17369.         b3dRemoveFill(fillList, face);
  17370.     } else {
  17371.         b3dAddBackFill(fillList, face);
  17372.         b3dCheckIntersectionOfFaces(fillList->firstFace, face, yValue, edge, nextIntersection);
  17373.     }
  17374.     face->flags ^= B3D_FACE_ACTIVE;
  17375.     face = edge->rightFace;
  17376.     if(face) {
  17377.         if(face->flags & B3D_FACE_ACTIVE) {
  17378.             b3dRemoveFill(fillList, face);
  17379.         } else {
  17380.             b3dAddBackFill(fillList, face);
  17381.             b3dCheckIntersectionOfFaces(fillList->firstFace, face, yValue, edge, nextIntersection);
  17382.         }
  17383.         face->flags ^= B3D_FACE_ACTIVE;
  17384.     }
  17385.     if(b3dDebug) b3dValidateFillList(fillList);
  17386. }
  17387. /* --INLINE-- */
  17388.  
  17389. /*************************************************************/
  17390. /*************************************************************/
  17391. /*************************************************************/
  17392.  
  17393. /* INLINE b3dClearSpanBuffer(aet) */
  17394. void b3dClearSpanBuffer(B3DActiveEdgeTable *aet)
  17395. {
  17396.     int i, leftX, rightX;
  17397.     unsigned int *buffer = currentState->spanBuffer;
  17398.     if(aet->size && buffer) {
  17399.         leftX = aet->data[0]->xValue >> B3D_FixedToIntShift;
  17400.         rightX = aet->data[aet->size-1]->xValue >> B3D_FixedToIntShift;
  17401.         if(leftX < 0) leftX = 0;
  17402.         if(rightX >= currentState->spanSize) rightX = currentState->spanSize-1;
  17403.         for(i=leftX;i<=rightX;i++) buffer[i] = 0;
  17404.     }
  17405. }
  17406. /* --INLINE-- */
  17407.  
  17408. /* INLINE b3dDrawSpanBuffer(aet, yValue) */
  17409. void b3dDrawSpanBuffer(B3DActiveEdgeTable *aet, int yValue)
  17410. {
  17411.     int leftX, rightX;
  17412.     if(aet->size && currentState->spanDrawer) {
  17413.         leftX = aet->data[0]->xValue >> B3D_FixedToIntShift;
  17414.         rightX = aet->data[aet->size-1]->xValue >> B3D_FixedToIntShift;
  17415.         if(leftX < 0) leftX = 0;
  17416.         if(rightX > currentState->spanSize) rightX = currentState->spanSize;
  17417.         currentState->spanDrawer(leftX, rightX, yValue);
  17418.     }
  17419. }
  17420. /* --INLINE-- */
  17421.  
  17422. /*************************************************************/
  17423. /*************************************************************/
  17424. /*************************************************************/
  17425. /* General failure */
  17426. #define FAIL(reason,resume) { aet->yValue = yValue; return reason | resume; }
  17427. #define PROCEED { yValue = aet->yValue; }
  17428.  
  17429. /* Failure adding objects */
  17430. #define FAIL_ADDING(reason) { obj->start = objStart; FAIL(reason, B3D_RESUME_ADDING) }
  17431. #define PROCEED_ADDING { objStart = obj->start; PROCEED }
  17432.  
  17433. /* Failure merging objects */
  17434. #define FAIL_MERGING(reason) { FAIL(reason, B3D_RESUME_MERGING); }
  17435. #define PROCEED_MERGING { PROCEED }
  17436.  
  17437. /* Failure during paint */
  17438. #define FAIL_PAINTING(reason) { aet->start = aetStart; aet->leftEdge = leftEdge; aet->rightEdge = rightEdge; FAIL(reason, B3D_RESUME_PAINTING) }
  17439. #define PROCEED_PAINTING(reason) { aetStart = aet->start; leftEdge = aet->leftEdge; rightEdge = aet->rightEdge; PROCEED }
  17440.  
  17441. #define FAIL_UPDATING(reason)
  17442.  
  17443. int b3dMainLoop(B3DRasterizerState *state, int stopReason)
  17444. {
  17445.     B3DPrimitiveObject *activeStart, *passiveStart;
  17446.     int yValue, nextObjY, nextEdgeY;
  17447.     B3DFillList *fillList;
  17448.     B3DPrimitiveEdge *lastIntersection, *nextIntersection;
  17449.  
  17450.  
  17451.     if(!!state)
  17452.         return B3D_GENERIC_ERROR;
  17453.  
  17454.     if(!!state->nObjects)
  17455.         return B3D_NO_ERROR;
  17456.  
  17457.     if(b3dValidateAndRemapState(state) !!= B3D_NO_ERROR)
  17458.         return B3D_GENERIC_ERROR;
  17459.  
  17460.     if(stopReason == B3D_NO_ERROR)
  17461.         b3dSetupObjects(state);
  17462.  
  17463.     if(b3dDebug) {
  17464.         /* check the sort order of objects */
  17465.         int i;
  17466.         for(i=2; i<state->nObjects;i++)
  17467.             if(!!objSortsBefore(state->objects[i-1], state->objects[i]))
  17468.                 b3dAbort("Objects not sorted");
  17469.     }
  17470.  
  17471.     currentState = state;
  17472.     faceAlloc = state->faceAlloc;
  17473.     edgeAlloc = state->edgeAlloc;
  17474.     attrAlloc = state->attrAlloc;
  17475.     addedEdges = state->addedEdges;
  17476.     fillList = state->fillList;
  17477.     aet = state->aet;
  17478.     nextIntersection = aet->nextIntersection;
  17479.     lastIntersection = aet->lastIntersection;
  17480.  
  17481.     if(b3dDoStats) nFaces = 0;
  17482.  
  17483.     if(stopReason == B3D_NO_ERROR) {
  17484.         activeStart = passiveStart = state->objects[0];
  17485.         yValue = nextEdgeY = nextObjY = passiveStart->minY;
  17486.     } else {
  17487.         int resumeCode;
  17488.         resumeCode = stopReason & B3D_RESUME_MASK;
  17489.         if(resumeCode == B3D_RESUME_ADDING  ) goto RESUME_ADDING;
  17490.         if(resumeCode == B3D_RESUME_MERGING ) goto RESUME_MERGING;
  17491.         if(resumeCode == B3D_RESUME_PAINTING) goto RESUME_PAINTING;
  17492.         if(resumeCode == B3D_RESUME_UPDATING) goto RESUME_UPDATING;
  17493.         return B3D_GENERIC_ERROR;
  17494.     }
  17495.  
  17496.     /**** BEGIN MAINLOOP ****/
  17497.     while(activeStart || passiveStart || aet->size) {
  17498.  
  17499. RESUME_ADDING:
  17500.  
  17501.         /* STEP 1: Add new objects if necessary */
  17502.         if(yValue == nextObjY) {
  17503.             nextEdgeY = nextObjY;
  17504.             while(passiveStart && passiveStart->minY == nextObjY) {
  17505.                 passiveStart->flags |= B3D_OBJECT_ACTIVE;
  17506.                 passiveStart = passiveStart->next;
  17507.             }
  17508.             if(passiveStart)
  17509.                 nextObjY = passiveStart->minY;
  17510.             else
  17511.                 nextObjY = 99999;
  17512.         } /* End of adding objects */
  17513.  
  17514.  
  17515.  
  17516.         /* STEP 2: Add new edges if necessary */
  17517.         if(yValue == nextEdgeY) {
  17518.             B3DPrimitiveObject *obj = activeStart;
  17519.             int scaledY = (yValue+1) << B3D_IntToFixedShift;
  17520.  
  17521.             nextEdgeY = nextObjY << B3D_IntToFixedShift;
  17522.             while(obj !!= passiveStart) {
  17523.                 B3DInputFace *objFaces = obj->faces;
  17524.                 B3DPrimitiveVertex *objVtx = obj->vertices;
  17525.                 int objStart = obj->start;
  17526.                 int objSize = obj->nFaces;
  17527.                 int tempY;
  17528.  
  17529.                 assert(obj->flags & B3D_OBJECT_ACTIVE);
  17530.  
  17531.                 while(objStart < objSize && ((tempY = objVtx[objFaces[objStart].i0].windowPosY) < scaledY)) {
  17532.                     /* add edges from face at objFaces[objStart] */
  17533.                     B3DInputFace *inputFace = objFaces + objStart;
  17534.                     B3DPrimitiveFace *face;
  17535.  
  17536.                     /* NOTE: If any of the following fails, 
  17537.                              we can re-enter the main loop later on. */
  17538.  
  17539.                     if(faceAlloc->nFree == 0)
  17540.                         FAIL_ADDING(B3D_NO_MORE_FACES);
  17541.                     
  17542.                     if(edgeAlloc->nFree < 2)
  17543.                         FAIL_ADDING(B3D_NO_MORE_EDGES);
  17544.  
  17545.                     if(addedEdges->size+2 > addedEdges->max)
  17546.                         FAIL_ADDING(B3D_NO_MORE_ADDED);
  17547.  
  17548.                     /* Allocate a new face and do the initial setup */
  17549.                     face = b3dInitializeFace(objVtx + inputFace->i0, 
  17550.                                              objVtx + inputFace->i1,
  17551.                                              objVtx + inputFace->i2,
  17552.                                              obj->texture,
  17553.                                              obj->flags);
  17554.                     if(face) {
  17555.                         b3dAddEdgesFromFace(face, yValue);
  17556.                     }
  17557.                     objStart++;
  17558.                 }
  17559.  
  17560.                 obj->start = objStart;
  17561.                 if(objStart !!= objSize) {
  17562.                     if(tempY < nextEdgeY) nextEdgeY = tempY;
  17563.                 } else {
  17564.                     /* Unlink obj from activeStart list */
  17565.                     obj->flags |= B3D_OBJECT_DONE;
  17566.                     if(obj == activeStart) {
  17567.                         activeStart = obj->next;
  17568.                     } else {
  17569.                         obj->prev->next = obj->next;
  17570.                     }
  17571.                 }
  17572.                 obj = obj->next;
  17573.             }
  17574.  
  17575.             nextEdgeY >>= B3D_FixedToIntShift;
  17576.         } /* End of adding edges */
  17577.  
  17578.  
  17579.         /* STEP 3: Merge all newly added edges from addedList into the AET */
  17580.         if(addedEdges->size) {
  17581. RESUME_MERGING:
  17582.             if(b3dDebug)
  17583.                 b3dValidateEdgeOrder(addedEdges);
  17584.             /* NOTE: If the following fails, we can re-enter the main loop later on. */
  17585.             if(aet->size + addedEdges->size > aet->max)
  17586.                 FAIL_MERGING(B3D_NO_MORE_AET);
  17587.             b3dMergeAETEdgesFrom(aet, addedEdges);
  17588.             if(b3dDebug) {
  17589.                 b3dValidateAETOrder(aet);
  17590.             }
  17591.             addedEdges->size = 0; /* reset added */
  17592.         } /* End of merging edges */
  17593.  
  17594.  
  17595.         /********** THIS IS THE CORE LOOP ********/
  17596.         /* while(yValue < nextEdgeY && !!addedEdges->size && aet->size) { */
  17597.  
  17598.             if(b3dDoStats) {
  17599.                 /* Gather stats */
  17600.                 if(aet->size > maxEdges) maxEdges = aet->size;
  17601.                 if(nFaces > maxFaces) maxFaces = nFaces;
  17602.             }
  17603.  
  17604.             /* STEP 4: Draw the current span */
  17605.  
  17606.             /* STEP 4a: Clear the span buffer */
  17607.             b3dClearSpanBuffer(aet);
  17608.  
  17609.             /* STEP 4b: Scan out the AET */
  17610.             if(aet->size) {
  17611.                 B3DPrimitiveEdge *leftEdge;
  17612.                 B3DPrimitiveEdge *rightEdge;
  17613.                 B3DPrimitiveEdge **aetData = aet->data;
  17614.                 int aetStart = 1;
  17615.                 int aetSize = aet->size;
  17616.  
  17617.                 /* clean up old fills if any */
  17618.                 b3dCleanupFill(fillList);
  17619.  
  17620.                 nextIntersection->xValue = B3D_MAX_X;
  17621.                 leftEdge = aetData[0];
  17622.                 while(aetStart < aetSize) {
  17623.  
  17624.                     /*-- Toggle the faces of the top edge (the left edge is always on top) --*/
  17625.                     if(leftEdge == lastIntersection) {
  17626.                         /* Special case if this is a intersection edge */
  17627.                         assert(fillList->firstFace == leftEdge->leftFace);
  17628.                         b3dRemoveFill(fillList, leftEdge->rightFace);
  17629.                         b3dAddFrontFill(fillList, leftEdge->rightFace);
  17630.                     } else {
  17631.                         b3dToggleTopFills(fillList, leftEdge, yValue);
  17632.                     }
  17633.                     /*-- end of toggling top edge faces --*/
  17634.  
  17635.                     /* after getting a new top fill we must adjust intersections */
  17636.                     b3dAdjustIntersections(fillList, yValue, leftEdge, nextIntersection);
  17637.  
  17638.                     /*-- search for the next top edge which will be the right edge --*/
  17639.                     assert(aetStart < aetSize);
  17640.                     if(!!fillList->firstFace)
  17641.                         rightEdge = aetData[aetStart++]; /* If no current top fill just use the next edge */
  17642.                     else while(aetStart < aetSize) { /* Search for the next top edge in the AET */
  17643.                         rightEdge = aetData[aetStart];
  17644.                         /* If we have an intersection use the intersection edge */
  17645.                         if(nextIntersection->xValue <= rightEdge->xValue) {
  17646.                             rightEdge = nextIntersection;
  17647.                             break;
  17648.                         }
  17649.                         aetStart++;
  17650.                         /* Check if this edge is on top */
  17651.                         assert(fillList->firstFace);
  17652.                         {
  17653.                             double xValue = rightEdge->xValue * B3D_FixedToFloat;
  17654.                             B3DPrimitiveFace *topFace = fillList->firstFace;
  17655.                             if( rightEdge->leftFace == topFace || 
  17656.                                 rightEdge->rightFace == topFace || 
  17657.                                 rightEdge->zValue < zValueAt(topFace, xValue, yValue))
  17658.                                 break; /* rightEdge is on top */
  17659.                         }
  17660.                         /* If the edge is not on top toggle its (back) fills */
  17661.                         b3dToggleBackFills(fillList, rightEdge, yValue, nextIntersection);
  17662.                         rightEdge = NULL;
  17663.                     }
  17664.                     /*-- end of search for next top edge --*/
  17665.  
  17666.                     /*-- Now do the drawing from leftEdge to rightEdge --*/
  17667.                     assert(rightEdge);
  17668.                     if(fillList->firstFace) {
  17669.                         /* Note: We fill *including* leftX and rightX */
  17670.                         int leftX = (leftEdge->xValue >> B3D_FixedToIntShift) + 1;
  17671.                         int rightX = (rightEdge->xValue >> B3D_FixedToIntShift);
  17672.                         B3DPrimitiveFace *topFace = fillList->firstFace;
  17673.  
  17674.                         if(leftX < 0) leftX = 0;
  17675.                         if(rightX >= currentState->spanSize) rightX = currentState->spanSize-1;
  17676.                         if(leftX <= rightX) {
  17677.                             /* Since we know now that some serious filling operation
  17678.                                will happen, initialize the attributes of the face if
  17679.                                this hasn''t been done before. */
  17680. RESUME_PAINTING:
  17681.                             if( (topFace->flags & B3D_FACE_INITIALIZED) == 0) {
  17682.                                 assert(topFace->attributes == NULL);
  17683.                                 if(!!b3dInitializePass2(topFace))
  17684.                                     FAIL_PAINTING(B3D_NO_MORE_ATTRS);
  17685.                             }
  17686.                             /* And dispatch on the actual pixel drawers */
  17687.                             (*B3D_FILL_FUNCTIONS[(topFace->flags >> B3D_ATTR_SHIFT) & B3D_ATTR_MASK])
  17688.                                 (leftX, rightX, yValue, topFace);
  17689.                         }
  17690.                     }
  17691.                     /*-- End of drawing -- */
  17692.  
  17693.                     /* prepare for new top edge */
  17694.                     leftEdge = rightEdge;
  17695.                     /* use a new intersection if necessary */
  17696.                     if(leftEdge == nextIntersection) {
  17697.                         nextIntersection = lastIntersection;
  17698.                         lastIntersection = leftEdge;
  17699.                     }
  17700.                     nextIntersection->xValue = B3D_MAX_X;
  17701.                 }
  17702.                 /* clean up old fills if any */
  17703.                 b3dCleanupFill(fillList);
  17704.             }
  17705.  
  17706.             /* STEP 4c: Display the pixels from the span buffer */
  17707.             b3dDrawSpanBuffer(aet, yValue);
  17708.  
  17709.             /* STEP 5: Go to next y value and update AET entries */
  17710.             yValue++;
  17711.             if(aet->size) {
  17712.                 int aetStart = 0;
  17713.                 int aetSize = aet->size;
  17714.                 B3DPrimitiveEdge **aetData = aet->data;
  17715.  
  17716.                 aetStart = 0;
  17717.                 while(aetStart < aetSize) {
  17718.                     B3DPrimitiveEdge *edge = aetData[aetStart];
  17719.  
  17720.                     if(--(edge->nLines)) {
  17721.                         /* Advance to next scan line and resort edge */
  17722.                         b3dAdvanceAETEdge(edge, aetData, aetStart);
  17723.                         aetStart++;
  17724.                     } else {
  17725.                         /* Remove edge and add lower edges if necessary */
  17726. RESUME_UPDATING:
  17727.                         if(edgeAlloc->nFree < 2)
  17728.                             FAIL_UPDATING(B3D_NO_MORE_EDGES);
  17729.                         if(addedEdges->size + 2 > addedEdges->max)
  17730.                             FAIL_UPDATING(B3D_NO_MORE_ADDED);
  17731.                         b3dRemoveAETEdge(aet, edge, yValue, aetStart);
  17732.                         aetSize = aet->size;
  17733.                         /* Do NOT advance aetStart here */
  17734.                     }
  17735.                 }
  17736.             }
  17737.             /* End of AET update */
  17738.             if(b3dDebug) {
  17739.                 b3dValidateAETOrder(aet);
  17740.             }
  17741.  
  17742.         /*}*/ /******** END OF CORE LOOP ********/
  17743.  
  17744.     }  /**** END MAINLOOP ****/
  17745.  
  17746.     return B3D_NO_ERROR;
  17747. }
  17748. '! !
  17749.  
  17750. !B3DRasterizerPlugin class methodsFor: 'C source code' stamp: 'ar 4/18/1999 08:33'!
  17751. b3dRemapC
  17752. ^'/****************************************************************************
  17753. *   PROJECT: Balloon 3D Graphics Subsystem for Squeak
  17754. *   FILE:    b3dRemap.c
  17755. *   CONTENT: Remapping functions for the B3D rasterizer
  17756. *
  17757. *   AUTHOR:  Andreas Raab (ar)
  17758. *   ADDRESS: Walt Disney Imagineering, Glendale, CA
  17759. *   EMAIL:   andreasr@wdi.disney.com
  17760. *   RCSID:   $Id$
  17761. *
  17762. *   NOTES:
  17763. *
  17764. *
  17765. *****************************************************************************/
  17766. #include "b3d.h"
  17767.  
  17768. /* b3dRemapFaces:
  17769.     Remap all allocated faces using the given offsets
  17770. */
  17771. /* INLINE b3dRemapFaces(list, attrOffset, edgeOffset) */
  17772. void b3dRemapFaces(B3DFaceAllocList *list, int attrOffset, int edgeOffset)
  17773. {
  17774.     int i;
  17775.  
  17776.     for(i=0; i<list->size;i++) {
  17777.         B3DPrimitiveFace *face = list->data + i;
  17778.         if(face->flags & B3D_ALLOC_FLAG) {
  17779.             if(face->attributes)
  17780.                 (char*)face->attributes += attrOffset;
  17781.             if(face->leftEdge)
  17782.                 (char*)face->leftEdge += edgeOffset;
  17783.             if(face->rightEdge)
  17784.                 (char*)face->rightEdge += edgeOffset;
  17785.         }
  17786.     }
  17787. }
  17788. /* --INLINE-- */
  17789.  
  17790. /* b3dRemapEdges:
  17791.     Remap all allocated edges using the given offset
  17792. */
  17793. /* INLINE b3dRemapEdges(list, faceOffset) */
  17794. void b3dRemapEdges(B3DEdgeAllocList *list, int faceOffset)
  17795. {
  17796.     int i;
  17797.     for(i=0; i<list->size;i++) {
  17798.         B3DPrimitiveEdge *edge = list->data + i;
  17799.         if(edge->flags & B3D_ALLOC_FLAG) {
  17800.             if(edge->leftFace)
  17801.                 (char*)edge->leftFace += faceOffset;
  17802.             if(edge->rightFace)
  17803.                 (char*)edge->rightFace += faceOffset;
  17804.         }
  17805.     }
  17806. }
  17807. /* --INLINE-- */
  17808.  
  17809. /* b3dRemapFills:
  17810.     Remap the fill list using the given offset
  17811. */
  17812. /* INLINE b3dRemapFills(fillList, offset) */
  17813. void b3dRemapFills(B3DFillList *fillList, int offset)
  17814. {
  17815.     B3DPrimitiveFace *temp;
  17816.     if(fillList->firstFace)
  17817.         (char*)fillList->firstFace += offset;
  17818.     if(fillList->lastFace)
  17819.         (char*)fillList->lastFace  += offset;
  17820.     temp = fillList->firstFace;
  17821.     while(temp) {
  17822.         if(temp->nextFace)
  17823.             (char*)temp->nextFace += offset;
  17824.         if(temp->prevFace)
  17825.             (char*)temp->prevFace += offset;
  17826.         temp = temp->nextFace;
  17827.     }
  17828. }
  17829. /* --INLINE-- */
  17830.  
  17831. /* b3dRemapEdgeList:
  17832.     Remap all edge pointers using the given offset
  17833. */
  17834. /* INLINE b3dRemapEdgeList(list, edgeOffset) */
  17835. void b3dRemapEdgeList(B3DPrimitiveEdgeList *list, int edgeOffset)
  17836. {
  17837.     int i;
  17838.     for(i=0; i<list->size;i++) {
  17839.         (char*) list->data[i] += edgeOffset;
  17840.     }
  17841. }
  17842. /* --INLINE-- */
  17843.  
  17844. /* b3dRemapAET:
  17845.     Remap all edge pointers using the given offset
  17846. */
  17847. /* INLINE b3dRemapAET(list, edgeOffset, aetOffset, firstEdge, lastEdge) */
  17848. void b3dRemapAET(B3DActiveEdgeTable *list, int edgeOffset, int aetOffset, void *firstEdge, void *lastEdge)
  17849. {
  17850.     int i;
  17851.     if(edgeOffset)
  17852.         for(i=0; i<list->size;i++)
  17853.             (char*) list->data[i] += edgeOffset;
  17854.  
  17855.     if((void*)list->leftEdge >= firstEdge && (void*)list->leftEdge < lastEdge)
  17856.         (char*) list->leftEdge += edgeOffset;
  17857.     else if(list->leftEdge)
  17858.         (char*) list->leftEdge += aetOffset;
  17859.  
  17860.     if((void*)list->rightEdge >= firstEdge && (void*)list->rightEdge < lastEdge)
  17861.         (char*) list->rightEdge += edgeOffset;
  17862.     else if(list->rightEdge)
  17863.         (char*) list->rightEdge += aetOffset;
  17864.  
  17865.     if(aetOffset) {
  17866.         (char*) list->nextIntersection += aetOffset;
  17867.         (char*) list->lastIntersection += aetOffset;
  17868.     }
  17869. }
  17870. /* --INLINE-- */
  17871.  
  17872. /* b3dRemapEdgeVertices:
  17873.     Remap all vertices in the specified range using the given offset
  17874. */
  17875. /* INLINE b3dRemapEdgeVertices(list, vtxOffset, firstVtx, lastVtx) */
  17876. void b3dRemapEdgeVertices(B3DEdgeAllocList *list, int vtxOffset, void *firstVtx, void *lastVtx)
  17877. {
  17878.     int i;
  17879.     for(i=0; i<list->size; i++) {
  17880.         B3DPrimitiveEdge *edge = list->data + i;
  17881.         if((edge->flags & B3D_ALLOC_FLAG) && ((void*)edge->v0 >= (void*)firstVtx) && ((void*)edge->v0 < (void*)lastVtx)) {
  17882.             (char*) edge->v0 += vtxOffset;
  17883.             (char*) edge->v1 += vtxOffset;
  17884.         }
  17885.     }
  17886. }
  17887. /* --INLINE-- */
  17888.  
  17889. /* b3dRemapFaceVertices:
  17890.     Remap all vertices in the specified range using the given offset
  17891. */
  17892. /* INLINE b3dRemapFaceVertices(list, vtxOffset, firstVtx, lastVtx) */
  17893. void b3dRemapFaceVertices(B3DFaceAllocList *list, int vtxOffset, void *firstVtx, void *lastVtx)
  17894. {
  17895.     int i;
  17896.     for(i=0; i<list->size; i++) {
  17897.         B3DPrimitiveFace *face = list->data + i;
  17898.         if((face->flags & B3D_ALLOC_FLAG) && ((void*)face->v0 >= (void*)firstVtx) && ((void*)face->v0 < (void*)lastVtx)) {
  17899.             (char*) face->v0 += vtxOffset;
  17900.             (char*) face->v1 += vtxOffset;
  17901.             (char*) face->v2 += vtxOffset;
  17902.         }
  17903.     }
  17904. }
  17905. /* --INLINE-- */
  17906.  
  17907. /* b3dRemapFaceFree:
  17908.     Remap all free faces using the given offset
  17909. */
  17910. /* INLINE b3dRemapFaceFree(list, faceOffset) */
  17911. void b3dRemapFaceFree(B3DFaceAllocList *list, int faceOffset)
  17912. {
  17913.     B3DPrimitiveFace *freeObj;
  17914.     if(list->firstFree) {
  17915.         (char*)list->firstFree += faceOffset;
  17916.         freeObj = list->firstFree;
  17917.         while(freeObj->nextFree) {
  17918.             (char*) freeObj->nextFree += faceOffset;
  17919.             freeObj = freeObj->nextFree;
  17920.         }
  17921.     }
  17922. }
  17923. /* --INLINE-- */
  17924.  
  17925. /* b3dRemapEdgeFree:
  17926.     Remap all free edges using the given offset
  17927. */
  17928. /* INLINE b3dRemapEdgeFree(list, edgeOffset) */
  17929. void b3dRemapEdgeFree(B3DEdgeAllocList *list, int edgeOffset)
  17930. {
  17931.     B3DPrimitiveEdge *freeObj;
  17932.     if(list->firstFree) {
  17933.         (char*)list->firstFree += edgeOffset;
  17934.         freeObj = list->firstFree;
  17935.         while(freeObj->nextFree) {
  17936.             (char*) freeObj->nextFree += edgeOffset;
  17937.             freeObj = freeObj->nextFree;
  17938.         }
  17939.     }
  17940. }
  17941. /* --INLINE-- */
  17942.  
  17943. /* b3dRemapAttrFree:
  17944.     Remap all free attributes using the given offset
  17945. */
  17946. /* INLINE b3dRemapAttrFree(list, attrOffset) */
  17947. void b3dRemapAttributes(B3DAttrAllocList *list, int attrOffset)
  17948. {
  17949.     int i;
  17950.     for(i=0; i < list->size; i++) {
  17951.         B3DPrimitiveAttribute *attr = list->data + i;
  17952.         if(attr->next)
  17953.             (char*) attr->next += attrOffset;
  17954.     }
  17955. }
  17956. /* --INLINE-- */
  17957.  
  17958. /* b3dValidateAndRemapState:
  17959.     Validate the rasterizer state and remap the objects if necessary.
  17960. */
  17961. int b3dValidateAndRemapState(B3DRasterizerState *state)
  17962. {
  17963.     int faceOffset, edgeOffset, attrOffset, aetOffset, objOffset, i;
  17964.     B3DPrimitiveObject *obj;
  17965.  
  17966.     if(!!state) return B3D_GENERIC_ERROR;
  17967.     
  17968.     /* Check the magic numbers */
  17969.     if(state->faceAlloc->magic  !!= B3D_FACE_ALLOC_MAGIC) return B3D_MAGIC_ERROR;
  17970.     if(state->edgeAlloc->magic  !!= B3D_EDGE_ALLOC_MAGIC) return B3D_MAGIC_ERROR;
  17971.     if(state->attrAlloc->magic  !!= B3D_ATTR_ALLOC_MAGIC) return B3D_MAGIC_ERROR;
  17972.     if(state->aet->magic        !!= B3D_AET_MAGIC) return B3D_MAGIC_ERROR;
  17973.     if(state->addedEdges->magic !!= B3D_EDGE_LIST_MAGIC) return B3D_MAGIC_ERROR;
  17974.     if(state->fillList->magic   !!= B3D_FILL_LIST_MAGIC) return B3D_MAGIC_ERROR;
  17975.  
  17976.     /* Check if we need to relocate objects */
  17977.     faceOffset = (int)state->faceAlloc - (int)state->faceAlloc->This;
  17978.     edgeOffset = (int)state->edgeAlloc - (int)state->edgeAlloc->This;
  17979.     attrOffset = (int)state->attrAlloc - (int)state->attrAlloc->This;
  17980.     aetOffset = (int)state->aet - (int)state->aet->This;
  17981.     
  17982.     /* remap faces */
  17983.     if(attrOffset || edgeOffset)
  17984.         b3dRemapFaces(state->faceAlloc, attrOffset, edgeOffset);
  17985.     
  17986.     /* remap fills and edges */
  17987.     if(faceOffset) {
  17988.         b3dRemapFills(state->fillList, faceOffset);
  17989.         b3dRemapEdges(state->edgeAlloc, faceOffset);
  17990.         b3dRemapFaceFree(state->faceAlloc, faceOffset);
  17991.     }
  17992.     
  17993.     /* Remap AET */
  17994.     if(edgeOffset || aetOffset) {
  17995.         void *firstEdge = state->edgeAlloc->data;
  17996.         void *lastEdge = state->edgeAlloc->data + state->edgeAlloc->size;
  17997.         b3dRemapAET(state->aet, edgeOffset, aetOffset, firstEdge, lastEdge);
  17998.     }
  17999.  
  18000.     /* Remap addedEdges and edge free list*/
  18001.     if(edgeOffset) {
  18002.         b3dRemapEdgeList(state->addedEdges, edgeOffset);
  18003.         b3dRemapEdgeFree(state->edgeAlloc, edgeOffset);
  18004.     }
  18005.  
  18006.     if(attrOffset)
  18007.         b3dRemapAttributes(state->attrAlloc, attrOffset);
  18008.     
  18009.     state->faceAlloc->This = (void*) state->faceAlloc;
  18010.     state->edgeAlloc->This = (void*) state->edgeAlloc;
  18011.     state->attrAlloc->This = (void*) state->attrAlloc;
  18012.     state->aet->This = (void*) state->aet;
  18013.  
  18014.     /* Remap any vertex pointers */
  18015.     for(i=0; i<state->nObjects; i++) {
  18016.         obj = state->objects[i];
  18017.         if(obj->magic !!= B3D_PRIMITIVE_OBJECT_MAGIC) return B3D_MAGIC_ERROR;
  18018.         objOffset = (int)obj - (int)obj->This;
  18019.         if(objOffset) {
  18020.             if((obj->flags & B3D_OBJECT_ACTIVE)) {
  18021.                 B3DPrimitiveVertex *firstVtx = obj->vertices;
  18022.                 B3DPrimitiveVertex *lastVtx = obj->vertices + obj->nVertices;
  18023.                 b3dRemapFaceVertices(state->faceAlloc, objOffset, firstVtx, lastVtx);
  18024.                 b3dRemapEdgeVertices(state->edgeAlloc, objOffset, firstVtx, lastVtx);
  18025.             }
  18026.             obj->vertices = (B3DPrimitiveVertex*) (obj + 1);
  18027.             obj->faces = (B3DInputFace*) (obj->vertices + obj->nVertices);
  18028.         }
  18029.         obj->This = (void*) obj;
  18030.     }
  18031.  
  18032.     return B3D_NO_ERROR;
  18033. }
  18034. '! !
  18035.  
  18036. !B3DRasterizerPlugin class methodsFor: 'C source code' stamp: 'di 4/22/1999 09:14'!
  18037. b3dTypesH
  18038. ^'/****************************************************************************
  18039. *   PROJECT: Balloon 3D Graphics Subsystem for Squeak
  18040. *   FILE:    b3dTypes.h
  18041. *   CONTENT: Type declarations for the B3D rasterizer
  18042. *
  18043. *   AUTHOR:  Andreas Raab (ar)
  18044. *   ADDRESS: Walt Disney Imagineering, Glendale, CA
  18045. *   EMAIL:   andreasr@wdi.disney.com
  18046. *   RCSID:   $Id$
  18047. *
  18048. *   NOTES:
  18049. *
  18050. *
  18051. *****************************************************************************/
  18052. #ifndef B3D_TYPES_H
  18053. #define B3D_TYPES_H
  18054.  
  18055. #ifndef NULL
  18056. #define NULL ((void*)0)
  18057. #endif
  18058.  
  18059. /* Error constants */
  18060. #define B3D_NO_ERROR 0
  18061. /* Generic error */
  18062. #define B3D_GENERIC_ERROR -1
  18063. /* Bad magic number */
  18064. #define B3D_MAGIC_ERROR -2
  18065.  
  18066. /* Note: The error codes that allow resuming
  18067.         must be positive. They''ll be combined
  18068.         with the resume codes */
  18069. /* no more space in edge allocation list */
  18070. #define B3D_NO_MORE_EDGES 1
  18071. /* no more space in face allocation list */
  18072. #define B3D_NO_MORE_FACES 2
  18073. /* no more space in attribute allocation list */
  18074. #define B3D_NO_MORE_ATTRS 3
  18075. /* no more space in active edge table */
  18076. #define B3D_NO_MORE_AET   4
  18077. /* no more space for added edges */
  18078. #define B3D_NO_MORE_ADDED 5
  18079.  
  18080. /* Resume codes */
  18081. #define B3D_RESUME_MASK 0xF0000
  18082. /* Resume adding objects/edges */
  18083. #define B3D_RESUME_ADDING   0x10000
  18084. /* Resume merging added edges */
  18085. #define B3D_RESUME_MERGING  0x20000
  18086. /* Resume painting faces */
  18087. #define B3D_RESUME_PAINTING 0x40000
  18088. /* Resume updating the AET */
  18089. #define B3D_RESUME_UPDATING 0x80000
  18090.  
  18091. /* Factor to convert from float to fixed pt */
  18092. #define B3D_FloatToFixed 4096.0
  18093. /* Factor to convert from fixed pt to float */
  18094. #define B3D_FixedToFloat 0.000244140625
  18095. /* Shift value to convert from integer to fixed pt */
  18096. #define B3D_IntToFixedShift 12
  18097. #define B3D_FixedToIntShift 12
  18098. /* 0.5 in fixed pt representation */
  18099. #define B3D_FixedHalf 2048
  18100.  
  18101. /* Max. possible x value */
  18102. #define B3D_MAX_X 0x7FFFFFFF
  18103.  
  18104. /* Allocation flag: If this flag is not set then the nextFree pointer is valid */
  18105. #define B3D_ALLOC_FLAG 1
  18106.  
  18107. /************************ PrimitiveColor definition ************************/
  18108. typedef unsigned char B3DPrimitiveColor[4];
  18109.  
  18110. /* An ugly hack but I can''t find the global defs in CodeWarrior on the Mac */
  18111. #ifndef LSB_FIRST
  18112.     #define MSB_FIRST
  18113. #endif
  18114.  
  18115. #ifndef MSB_FIRST
  18116.     #define RED_INDEX 0
  18117.     #define GREEN_INDEX 1
  18118.     #define BLUE_INDEX 2
  18119.     #define ALPHA_INDEX 3
  18120. #else
  18121.     #define ALPHA_INDEX 0
  18122.     #define BLUE_INDEX 1
  18123.     #define GREEN_INDEX 2
  18124.     #define RED_INDEX 3
  18125. #endif
  18126.  
  18127. /************************ PrimitiveVertex definition ************************/
  18128. typedef struct B3DPrimitiveVertex {
  18129.     float position[3];
  18130.     float normal[3];
  18131.     float texCoord[2];
  18132.     float rasterPos[4];
  18133.     union {
  18134.         int pixelValue32;
  18135.         B3DPrimitiveColor color;
  18136.     } cc;
  18137.     int clipFlags;
  18138.     int windowPos[2];
  18139. } B3DPrimitiveVertex;
  18140.  
  18141. /* sort order for primitive vertices */
  18142. #define vtxSortsBefore(vtx1, vtx2) ( (vtx1)->windowPosY == (vtx2)->windowPosY ? (vtx1)->windowPosX <= (vtx2)->windowPosX : (vtx1)->windowPosY <= (vtx2)->windowPosY)
  18143.  
  18144. /************************ InputFace definition ************************/
  18145. /* Note: The following is mainly so that we don''t need these weird int[3] declarations. */
  18146. typedef struct B3DInputFace {
  18147.     int i0;
  18148.     int i1;
  18149.     int i2;
  18150. } B3DInputFace;
  18151.  
  18152. typedef struct B3DInputQuad {
  18153.     int i0;
  18154.     int i1;
  18155.     int i2;
  18156.     int i3;
  18157. } B3DInputQuad;
  18158.  
  18159. /************************ PrimitiveEdge definition ************************/
  18160. /* Edge flags:
  18161.     B3D_EDGE_CONTINUE_LEFT  - continue with the lower edge of the left face
  18162.     B3D_EDGE_CONTINUE_RIGHT - continue with the lower edge of the right face
  18163.     B3D_EDGE_LEFT_MAJOR     - edge is major edge for left face
  18164.     B3D_EDGE_RIGHT_MAJOR    - edge is major edge for right face
  18165. */
  18166.  
  18167. #define B3D_EDGE_CONTINUE_LEFT  0x10
  18168. #define B3D_EDGE_CONTINUE_RIGHT 0x20
  18169. #define B3D_EDGE_LEFT_MAJOR     0x40
  18170. #define B3D_EDGE_RIGHT_MAJOR    0x80
  18171.  
  18172. typedef struct B3DPrimitiveEdge {
  18173.     int flags;
  18174.     struct B3DPrimitiveEdge *nextFree;
  18175.  
  18176.     /* start/end of edge */
  18177.     struct B3DPrimitiveVertex *v0;
  18178.     struct B3DPrimitiveVertex *v1;
  18179.  
  18180.     /* left/right face of edge (NOT meant literally) */
  18181.     struct B3DPrimitiveFace *leftFace;
  18182.     struct B3DPrimitiveFace *rightFace;
  18183.  
  18184.     /* current x/z value */
  18185.     int xValue;
  18186.     float zValue;
  18187.     /* x/z increment per scan line */
  18188.     int xIncrement;
  18189.     float zIncrement;
  18190.  
  18191.     /* number of remaining scan lines */
  18192.     int nLines;
  18193. } B3DPrimitiveEdge;
  18194.  
  18195.  
  18196. /* B3DPrimitiveEdgeList: A list of pointers to primitive edges */
  18197. #define B3D_EDGE_LIST_MAGIC  0x45553342
  18198. typedef struct B3DPrimitiveEdgeList {
  18199.     int magic;
  18200.     void *This;
  18201.     int start;
  18202.     int size;
  18203.     int max;
  18204.     B3DPrimitiveEdge *data[1];
  18205. } B3DPrimitiveEdgeList;
  18206.  
  18207. /* B3DActiveEdgeTable: The active edge table (basically a primitive
  18208.     edge table with few additional entries) */
  18209. #define B3D_AET_MAGIC   0x41455420
  18210. typedef struct B3DActiveEdgeTable {
  18211.     int magic;
  18212.     void *This;
  18213.     int start;
  18214.     int size;
  18215.     int max;
  18216.     /* Backups for proceeding after failure */
  18217.     int yValue;
  18218.     B3DPrimitiveEdge *leftEdge;
  18219.     B3DPrimitiveEdge *rightEdge;
  18220.     B3DPrimitiveEdge *lastIntersection;
  18221.     B3DPrimitiveEdge *nextIntersection;
  18222.     /* That''s where lastIntersection and nextIntersection point to */
  18223.     B3DPrimitiveEdge tempEdge0;
  18224.     B3DPrimitiveEdge tempEdge1;
  18225.     /* Actual data */
  18226.     B3DPrimitiveEdge *data[1];
  18227. } B3DActiveEdgeTable ;
  18228.  
  18229. /************************ PrimitiveFace definition ************************/
  18230.  
  18231. /* Face flags:
  18232.     B3D_FACE_INITIALIZED - have the face attributes been initialized?!!
  18233.     B3D_FACE_ACTIVE      - is the face currently in the fill list?!!
  18234.     B3D_FACE_HAS_ALPHA   - can the face eventually be transparent?!!
  18235.  
  18236.     B3D_FACE_RGB         - R,G,B interpolation values
  18237.     B3D_FACE_ALPHA       - Alpha interpolation values
  18238.     B3D_FACE_STW         - S,T,W interpolation values
  18239. */
  18240.  
  18241. #define B3D_FACE_INITIALIZED 0x10
  18242. #define B3D_FACE_ACTIVE      0x20
  18243. #define B3D_FACE_HAS_ALPHA   0x40
  18244.  
  18245. #define B3D_FACE_RGB         0x100
  18246. #define B3D_FACE_ALPHA       0x200
  18247. #define B3D_FACE_STW         0x400
  18248.  
  18249. /* # of possible combinations AND maximum (e.g., R+G+B+A+S+T+W) of attribs */
  18250. /* NOTE: This is a really ugly hack - I''ll have to fix that */
  18251. #define B3D_MAX_ATTRIBUTES 8
  18252. /* mask out the face attributes */
  18253. #define B3D_ATTR_MASK 0x7
  18254. /* shift for getting the attributes */
  18255. #define B3D_ATTR_SHIFT 8
  18256.  
  18257. typedef struct B3DPrimitiveFace {
  18258.     int flags;
  18259.     struct B3DPrimitiveFace *nextFree;
  18260.  
  18261.     /* The three vertices of the face */
  18262.     struct B3DPrimitiveVertex *v0;
  18263.     struct B3DPrimitiveVertex *v1;
  18264.     struct B3DPrimitiveVertex *v2;
  18265.  
  18266.     /* The links for the (depth sorted) list of fills */
  18267.     struct B3DPrimitiveFace *prevFace;
  18268.     struct B3DPrimitiveFace *nextFace;
  18269.  
  18270.     /* The left and right edge of the face (not taken too literally) */
  18271.     struct B3DPrimitiveEdge *leftEdge;
  18272.     struct B3DPrimitiveEdge *rightEdge;
  18273.  
  18274.     /* The deltas for the major (e.g., v0-v2) and the first minor (e.g., v0-v1) edge */
  18275.     float majorDx, majorDy;
  18276.     float minorDx, minorDy;
  18277.  
  18278.     /* The inverse area covered by (twice) the triangle */
  18279.     float oneOverArea;
  18280.  
  18281.     /* Depth attributes are kept here since we almost always need ''em */
  18282.     float minZ, maxZ;
  18283.     float dzdx, dzdy;
  18284.  
  18285.     /* The pointer to the texture */
  18286.     struct B3DTexture *texture;
  18287.     /* The pointer to the extended (per face) interpolation values */
  18288.     struct B3DPrimitiveAttribute *attributes;
  18289. } B3DPrimitiveFace;
  18290.  
  18291.  
  18292. /* B3DFillList: A (depth-sorted) list of primitive faces */
  18293. #define B3D_FILL_LIST_MAGIC  0x46443342
  18294. typedef struct B3DFillList {
  18295.     int magic;
  18296.     void *This;
  18297.     B3DPrimitiveFace *firstFace;
  18298.     B3DPrimitiveFace *lastFace;
  18299. } B3DFillList;
  18300.  
  18301. /************************ PrimitiveAttribute definition ************************/
  18302.  
  18303. typedef struct B3DPrimitiveAttribute {
  18304.     /* Note: next is either nextFree or or nextUsed */
  18305.     struct B3DPrimitiveAttribute *next;
  18306.     /* value at the face->v0 */
  18307.     float value;
  18308.     /* value / dx derivative for face */
  18309.     float dvdx;
  18310.     /* value / dy derivative for face */
  18311.     float dvdy;
  18312. } B3DPrimitiveAttribute;
  18313.  
  18314. /************************ Texture definition ************************/
  18315. #define B3D_TEXTURE_POWER_OF_2 0x10
  18316. typedef struct B3DTexture {
  18317.     int width;
  18318.     int height;
  18319.     int depth;
  18320.     int rowLength; /* 32bit words per scan line */
  18321.     int sMask;    /* Nonzero for power of two width */
  18322.     int sShift;
  18323.     int tMask;    /* Nonzero for power of two height */
  18324.     int tShift;
  18325.     int cmSize; /* length of color map */
  18326.     unsigned int *colormap;
  18327.     unsigned int *data;
  18328. } B3DTexture;
  18329.  
  18330. /************************ PrimitiveViewport definition ************************/
  18331.  
  18332. typedef struct B3DPrimitiveViewport {
  18333.     int x0, y0, x1, y1;
  18334. } B3DPrimitiveViewport;
  18335.  
  18336. /************************ PrimitiveObject definition ************************/
  18337. #define B3D_OBJECT_ACTIVE 0x10
  18338. #define B3D_OBJECT_DONE   0x20
  18339.  
  18340. #define B3D_PRIMITIVE_OBJECT_MAGIC  0x4F443342
  18341. typedef struct B3DPrimitiveObject {
  18342.     int magic;
  18343.     void *This;
  18344.     int __oop__; /* actual ST oop */
  18345.     struct B3DPrimitiveObject *next;
  18346.     struct B3DPrimitiveObject *prev;
  18347.  
  18348.     int flags;
  18349.  
  18350.     int textureIndex;
  18351.     struct B3DTexture *texture;
  18352.  
  18353.     int minX, maxX, minY, maxY;
  18354.     float minZ, maxZ;
  18355.  
  18356.     int nSortedFaces;
  18357.     int nInvalidFaces;
  18358.     
  18359.  
  18360.     int start;
  18361.     int nFaces;
  18362.     B3DInputFace *faces;
  18363.     int nVertices;
  18364.     B3DPrimitiveVertex *vertices;
  18365. } B3DPrimitiveObject;
  18366.  
  18367. /* sort order for primitive objects */
  18368. #define objSortsBefore(obj1, obj2) ( (obj1)->minY == (obj2)->minY ? (obj1)->minX <= (obj2)->minX : (obj1)->minY <= (obj2)->minY)
  18369.  
  18370. #endif /* ifndef B3D_TYPES_H */
  18371. '! !
  18372.  
  18373. I represent a facade for all Balloon 3D operations. Clients should only interact with me, not with any of the parts of the engine directly. However, clients may configure me to use certain parts in the 3D rendering pipeline.
  18374.  
  18375. Instance variables: 
  18376.     vertexBuffer     <B3DVertexBuffer>    The vertex buffer passed on through the entire pipeline
  18377.     transformer     <B3DEnginePart>        The part performing transform operations
  18378.     shader             <B3DEnginePart>        The part performing vertex shading operations
  18379.     clipper             <B3DEnginePart>        The part performing view frustum clipping
  18380.     rasterizer        <B3DEnginePart>        The part performing final pixel rasterization
  18381. !
  18382. !B3DRenderEngine methodsFor: 'attributes' stamp: 'ar 2/14/1999 22:22'!
  18383. clearDepthBuffer
  18384.     ^rasterizer clearDepthBuffer! !
  18385.  
  18386. !B3DRenderEngine methodsFor: 'attributes' stamp: 'ar 2/16/1999 02:17'!
  18387. clearViewport: aColor
  18388.     ^rasterizer clearViewport: aColor! !
  18389.  
  18390. !B3DRenderEngine methodsFor: 'attributes'!
  18391. color
  18392.     ^vertexBuffer color! !
  18393.  
  18394. !B3DRenderEngine methodsFor: 'attributes'!
  18395. color: aColor
  18396.     ^vertexBuffer color: aColor! !
  18397.  
  18398. !B3DRenderEngine methodsFor: 'attributes' stamp: 'ar 2/7/1999 19:34'!
  18399. material
  18400.     ^shader material! !
  18401.  
  18402. !B3DRenderEngine methodsFor: 'attributes' stamp: 'ar 2/7/1999 19:34'!
  18403. material: aMaterial
  18404.     ^shader material: aMaterial! !
  18405.  
  18406. !B3DRenderEngine methodsFor: 'attributes' stamp: 'ar 2/7/1999 16:19'!
  18407. materialColor
  18408.     ^shader materialColor! !
  18409.  
  18410. !B3DRenderEngine methodsFor: 'attributes' stamp: 'ar 2/7/1999 16:19'!
  18411. materialColor: aColor
  18412.     ^shader materialColor: aColor! !
  18413.  
  18414. !B3DRenderEngine methodsFor: 'attributes'!
  18415. normal
  18416.     ^vertexBuffer normal! !
  18417.  
  18418. !B3DRenderEngine methodsFor: 'attributes'!
  18419. normal: aVector
  18420.     ^vertexBuffer normal: aVector! !
  18421.  
  18422. !B3DRenderEngine methodsFor: 'attributes' stamp: 'ar 2/7/1999 19:35'!
  18423. popMaterial
  18424.     ^shader popMaterial.! !
  18425.  
  18426. !B3DRenderEngine methodsFor: 'attributes' stamp: 'ar 2/16/1999 03:14'!
  18427. popTexture
  18428.     ^rasterizer popTexture! !
  18429.  
  18430. !B3DRenderEngine methodsFor: 'attributes' stamp: 'ar 2/7/1999 19:34'!
  18431. pushMaterial
  18432.     ^shader pushMaterial.! !
  18433.  
  18434. !B3DRenderEngine methodsFor: 'attributes' stamp: 'ar 2/16/1999 03:14'!
  18435. pushTexture
  18436.     ^rasterizer pushTexture! !
  18437.  
  18438. !B3DRenderEngine methodsFor: 'attributes'!
  18439. texCoords
  18440.     ^vertexBuffer texCoords! !
  18441.  
  18442. !B3DRenderEngine methodsFor: 'attributes'!
  18443. texCoords: aVector
  18444.     ^vertexBuffer texCoords: aVector! !
  18445.  
  18446. !B3DRenderEngine methodsFor: 'attributes' stamp: 'ar 2/16/1999 03:14'!
  18447. texture
  18448.     ^rasterizer texture! !
  18449.  
  18450. !B3DRenderEngine methodsFor: 'attributes' stamp: 'ar 6/2/1999 14:00'!
  18451. texture: anObject
  18452.     "Note: For convenience; the object can be anything that understands #asTexture"
  18453.     ^rasterizer texture: anObject asTexture! !
  18454.  
  18455. !B3DRenderEngine methodsFor: 'attributes'!
  18456. vertex
  18457.     ^vertexBuffer vertex! !
  18458.  
  18459. !B3DRenderEngine methodsFor: 'attributes'!
  18460. vertex: aVector
  18461.     ^vertexBuffer vertex: aVector.! !
  18462.  
  18463. !B3DRenderEngine methodsFor: 'attributes' stamp: 'ar 2/4/1999 17:52'!
  18464. viewport
  18465.     ^rasterizer viewport! !
  18466.  
  18467. !B3DRenderEngine methodsFor: 'attributes' stamp: 'ar 2/4/1999 17:52'!
  18468. viewport: aRect
  18469.     ^rasterizer viewport: aRect! !
  18470.  
  18471. !B3DRenderEngine methodsFor: 'draw primitives' stamp: 'ar 11/7/1999 18:12'!
  18472. drawPolygonAfter: aBlock
  18473.     vertexBuffer reset.
  18474.     vertexBuffer primitive: 3.
  18475.     aBlock value.
  18476.     ^self renderPrimitive.! !
  18477.  
  18478. !B3DRenderEngine methodsFor: 'draw primitives' stamp: 'ar 11/7/1999 18:15'!
  18479. drawPolygonMesh: aB3DPolygonMesh
  18480.     "Draw a generic polygon mesh"
  18481.     | hasVtxNormals hasTexCoords hasVtxColors bounds box |
  18482.     box _ nil.
  18483.     aB3DPolygonMesh polygonsDo:[:poly|
  18484.         hasVtxNormals _ poly hasVertexNormals.
  18485.         hasTexCoords _ poly hasTextureCoords.
  18486.         hasVtxColors _ poly hasVertexColors.
  18487.         "Set the normal of the polygon if we don't have normals per vertex"
  18488.         hasVtxNormals 
  18489.             ifFalse:[self normal: poly normal].
  18490.         bounds _ self drawPolygonAfter:[
  18491.             poly verticesDo:[:vtx|
  18492.                 hasVtxColors ifTrue:[self color: (poly colorOfVertex: vtx)].
  18493.                 hasVtxNormals ifTrue:[self normal: (poly normalOfVertex: vtx)].
  18494.                 hasTexCoords ifTrue:[self texCoord: (poly texCoordOfVertex: vtx)].
  18495.                 self vertex: vtx.
  18496.             ].
  18497.         ].
  18498.         box == nil ifTrue:[box _ bounds] ifFalse:[box _ box quickMerge: bounds].
  18499.     ].
  18500.     ^box! !
  18501.  
  18502. !B3DRenderEngine methodsFor: 'draw primitives' stamp: 'ar 2/4/1999 20:16'!
  18503. render: anObject
  18504.     anObject renderOn: self.! !
  18505.  
  18506. !B3DRenderEngine methodsFor: 'private-rendering' stamp: 'ar 2/8/1999 15:37'!
  18507. privateClipVB: vb
  18508.     "Clip the objects in the vertex buffer."
  18509.     ^clipper processVertexBuffer: vb! !
  18510.  
  18511. !B3DRenderEngine methodsFor: 'private-rendering' stamp: 'ar 2/2/1999 19:39'!
  18512. privateNeedsClipVB: visibleFlag
  18513.     "Determine if a vertex buffer with the given visibility flag must be clipped.
  18514.     Return false if either visibleFlag == true (meaning the vertex buffer is completely inside the view frustum) or the rasterizer can clip by itself (it usually can)."
  18515.     ^visibleFlag ~~ true and:[rasterizer needsClip]! !
  18516.  
  18517. !B3DRenderEngine methodsFor: 'private-rendering'!
  18518. privateNeedsShadingVB
  18519.     "Return true if the objects in the vertex buffer needs separate shading.
  18520.     This is determined by checking if
  18521.         a) lighting is enabled
  18522.         b) at least one light exists
  18523.         c) at least one material exists
  18524.     "
  18525.     ^true! !
  18526.  
  18527. !B3DRenderEngine methodsFor: 'private-rendering' stamp: 'ar 2/4/1999 04:26'!
  18528. privateRasterizeVB: vb
  18529.     "Rasterize the current primitive from the vertex buffer."
  18530.     ^rasterizer processVertexBuffer: vb! !
  18531.  
  18532. !B3DRenderEngine methodsFor: 'private-rendering' stamp: 'ar 2/4/1999 04:26'!
  18533. privateShadeVB: vb
  18534.     "Shade all the vertices in the vertex buffer using selected materials and lights"
  18535.     ^shader processVertexBuffer: vb! !
  18536.  
  18537. !B3DRenderEngine methodsFor: 'private-rendering' stamp: 'ar 2/8/1999 21:18'!
  18538. privateTransformVB: vb
  18539.     "Transform the contents of the vertex buffer.
  18540.     Transforming may include normals (if lighting enabled) and textures (if textures enabled)."
  18541.     ^transformer processVertexBuffer: vb! !
  18542.  
  18543. !B3DRenderEngine methodsFor: 'private-rendering' stamp: 'ar 2/2/1999 19:31'!
  18544. privateVisibleVB: vb
  18545.     "Return the visibility of the objects in the vertex buffer.
  18546.     Return:
  18547.         true - if completely inside view frustum
  18548.         false - if completely outside view frustum
  18549.         nil - if partly inside/outside view frustum
  18550.     "! !
  18551.  
  18552. !B3DRenderEngine methodsFor: 'private-rendering' stamp: 'ar 11/7/1999 18:11'!
  18553. renderPrimitive
  18554.     "This is the main rendering loop for all operations"
  18555.     | visible |
  18556.     "Step 1: Check if the mesh is visible at all"
  18557.     visible _ self privateVisibleVB: vertexBuffer.
  18558.     visible == false ifTrue:[^nil].
  18559.  
  18560.     "Step 2: Transform vertices, normals, texture coords of the mesh"
  18561.     self privateTransformVB: vertexBuffer.
  18562.  
  18563.     "Step 3: Light the vertices of the mesh."
  18564.     self privateNeedsShadingVB
  18565.         ifTrue:[self privateShadeVB: vertexBuffer].
  18566.  
  18567.     "Step 4: Clip the mesh if necessary"
  18568.     (self privateNeedsClipVB: visible)
  18569.         ifTrue:[visible _ self privateClipVB: vertexBuffer].
  18570.     visible == false ifTrue:[^nil].
  18571.  
  18572.     "Step 5: Rasterize the mesh"
  18573.     ^self privateRasterizeVB: vertexBuffer.! !
  18574.  
  18575. !B3DRenderEngine methodsFor: 'transforming' stamp: 'ar 2/4/1999 20:18'!
  18576. loadIdentity
  18577.     ^transformer loadIdentity! !
  18578.  
  18579. !B3DRenderEngine methodsFor: 'transforming'!
  18580. lookFrom: position to: target up: upDirection
  18581.     ^transformer lookFrom: position to: target up: upDirection! !
  18582.  
  18583. !B3DRenderEngine methodsFor: 'transforming'!
  18584. perspective: aPerspective
  18585.     ^transformer perspective: aPerspective! !
  18586.  
  18587. !B3DRenderEngine methodsFor: 'transforming' stamp: 'ar 2/5/1999 23:27'!
  18588. popMatrix
  18589.     ^transformer popMatrix! !
  18590.  
  18591. !B3DRenderEngine methodsFor: 'transforming' stamp: 'ar 2/5/1999 23:27'!
  18592. pushMatrix
  18593.     ^transformer pushMatrix! !
  18594.  
  18595. !B3DRenderEngine methodsFor: 'transforming'!
  18596. rotateBy: aRotation
  18597.     ^transformer rotateBy: aRotation! !
  18598.  
  18599. !B3DRenderEngine methodsFor: 'transforming' stamp: 'ar 2/15/1999 02:54'!
  18600. scaleBy: value
  18601.     ^transformer scaleBy: value! !
  18602.  
  18603. !B3DRenderEngine methodsFor: 'transforming'!
  18604. transformBy: aTransformation
  18605.     ^transformer transformBy: aTransformation! !
  18606.  
  18607. !B3DRenderEngine methodsFor: 'transforming' stamp: 'ar 2/4/1999 03:56'!
  18608. translateBy: aVector
  18609.     ^transformer translateBy: aVector! !
  18610.  
  18611. !B3DRenderEngine methodsFor: 'initialize' stamp: 'ar 2/16/1999 01:46'!
  18612. destroy
  18613.     "Utility - destroy all resources associated with any part of the engine"
  18614.     transformer destroy.
  18615.     shader destroy.
  18616.     clipper destroy.
  18617.     rasterizer destroy.! !
  18618.  
  18619. !B3DRenderEngine methodsFor: 'initialize' stamp: 'ar 2/16/1999 01:45'!
  18620. finish
  18621.     "Flush the pipeline and force changes to the output medium"
  18622.     self flush.
  18623.     rasterizer finish.! !
  18624.  
  18625. !B3DRenderEngine methodsFor: 'initialize' stamp: 'ar 2/5/1999 21:34'!
  18626. flush
  18627.     "Flush the entire pipeline"
  18628.     transformer flush.
  18629.     shader flush.
  18630.     clipper flush.
  18631.     rasterizer flush.! !
  18632.  
  18633. !B3DRenderEngine methodsFor: 'initialize' stamp: 'ar 4/18/1999 00:35'!
  18634. initialize
  18635.     engine _ self. "Obviously ;-)"
  18636.     vertexBuffer _ B3DVertexBuffer new.
  18637.     transformer _ self class transformer engine: self.
  18638.     shader _ self class shader engine: self.
  18639.     clipper _ self class clipper engine: self.
  18640.     rasterizer _ self class rasterizer engine: self.
  18641.     self materialColor: Color white.! !
  18642.  
  18643. !B3DRenderEngine methodsFor: 'initialize' stamp: 'ar 4/10/1999 22:51'!
  18644. reset
  18645.     vertexBuffer reset.
  18646.     transformer reset.
  18647.     shader reset.
  18648.     clipper reset.
  18649.     rasterizer reset.
  18650.     self materialColor: Color white.! !
  18651.  
  18652. !B3DRenderEngine methodsFor: 'shading' stamp: 'ar 2/15/1999 20:24'!
  18653. addLight: aLightSource
  18654.     "Add the given light source to the engine.
  18655.     Return a handle that can be used to modify the light source later on"
  18656.     ^shader addLight: (aLightSource transformedBy: transformer)! !
  18657.  
  18658. !B3DRenderEngine methodsFor: 'shading' stamp: 'ar 2/15/1999 20:25'!
  18659. removeLight: lightHandle
  18660.     "Remove the light with the given handle from the engine."
  18661.     ^shader removeLight: lightHandle! !
  18662.  
  18663. !B3DRenderEngine methodsFor: 'shading' stamp: 'ar 2/8/1999 02:30'!
  18664. trackAmbientColor
  18665.     ^vertexBuffer trackAmbientColor! !
  18666.  
  18667. !B3DRenderEngine methodsFor: 'shading' stamp: 'ar 2/8/1999 02:30'!
  18668. trackAmbientColor: aBoolean
  18669.     ^vertexBuffer trackAmbientColor: aBoolean! !
  18670.  
  18671. !B3DRenderEngine methodsFor: 'shading' stamp: 'ar 2/8/1999 02:31'!
  18672. trackDiffuseColor
  18673.     ^vertexBuffer trackDiffuseColor! !
  18674.  
  18675. !B3DRenderEngine methodsFor: 'shading' stamp: 'ar 2/8/1999 02:30'!
  18676. trackDiffuseColor: aBoolean
  18677.     ^vertexBuffer trackDiffuseColor: aBoolean! !
  18678.  
  18679. !B3DRenderEngine methodsFor: 'shading' stamp: 'ar 2/8/1999 02:31'!
  18680. trackEmissionColor
  18681.     ^vertexBuffer trackEmissionColor! !
  18682.  
  18683. !B3DRenderEngine methodsFor: 'shading' stamp: 'ar 2/8/1999 02:30'!
  18684. trackEmissionColor: aBoolean
  18685.     ^vertexBuffer trackEmissionColor: aBoolean! !
  18686.  
  18687. !B3DRenderEngine methodsFor: 'shading' stamp: 'ar 2/8/1999 02:31'!
  18688. trackSpecularColor
  18689.     ^vertexBuffer trackSpecularColor! !
  18690.  
  18691. !B3DRenderEngine methodsFor: 'shading' stamp: 'ar 2/8/1999 02:30'!
  18692. trackSpecularColor: aBoolean
  18693.     ^vertexBuffer trackSpecularColor: aBoolean! !
  18694.  
  18695. !B3DRenderEngine methodsFor: 'indexed primitives' stamp: 'ar 11/7/1999 18:12'!
  18696. drawIndexedLines: indexArray vertices: vertexArray normals: normalArray colors: colorArray texCoords: texCoordArray
  18697.     vertexBuffer reset.
  18698.     vertexBuffer primitive: 4.
  18699.     vertexBuffer 
  18700.         loadIndexed: indexArray
  18701.         vertices: vertexArray 
  18702.         normals: normalArray 
  18703.         colors: colorArray 
  18704.         texCoords: texCoordArray.
  18705.     ^self renderPrimitive.! !
  18706.  
  18707. !B3DRenderEngine methodsFor: 'indexed primitives' stamp: 'ar 11/7/1999 18:12'!
  18708. drawIndexedQuads: indexArray vertices: vertexArray normals: normalArray colors: colorArray texCoords: texCoordArray
  18709.     vertexBuffer reset.
  18710.     vertexBuffer primitive: 6.
  18711.     vertexBuffer 
  18712.         loadIndexed: indexArray
  18713.         vertices: vertexArray 
  18714.         normals: normalArray 
  18715.         colors: colorArray 
  18716.         texCoords: texCoordArray.
  18717.     ^self renderPrimitive.! !
  18718.  
  18719. !B3DRenderEngine methodsFor: 'indexed primitives' stamp: 'ar 11/7/1999 18:12'!
  18720. drawIndexedTriangles: indexArray vertices: vertexArray normals: normalArray colors: colorArray texCoords: texCoordArray
  18721.     vertexBuffer reset.
  18722.     vertexBuffer primitive: 5.
  18723.     vertexBuffer 
  18724.         loadIndexed: indexArray
  18725.         vertices: vertexArray 
  18726.         normals: normalArray 
  18727.         colors: colorArray 
  18728.         texCoords: texCoordArray.
  18729.     ^self renderPrimitive.! !
  18730.  
  18731. !B3DRenderEngine methodsFor: 'private-access' stamp: 'ar 5/26/2000 15:20'!
  18732. clipRect
  18733.     "Return the current clipRect"
  18734.     ^rasterizer clipRect! !
  18735.  
  18736. !B3DRenderEngine methodsFor: 'private-access' stamp: 'ar 5/26/2000 15:20'!
  18737. clipRect: aRectangle
  18738.     "Set the current clipRect"
  18739.     ^rasterizer clipRect: aRectangle! !
  18740.  
  18741. !B3DRenderEngine methodsFor: 'private-access' stamp: 'ar 4/17/1999 23:12'!
  18742. getClipper
  18743.     "Private. Return the clipper used with this engine."
  18744.     ^clipper! !
  18745.  
  18746. !B3DRenderEngine methodsFor: 'private-access' stamp: 'ar 4/17/1999 23:13'!
  18747. getRasterizer
  18748.     "Private. Return the rasterizer used with this engine."
  18749.     ^rasterizer! !
  18750.  
  18751. !B3DRenderEngine methodsFor: 'private-access' stamp: 'ar 4/17/1999 23:12'!
  18752. getShader
  18753.     "Private. Return the shader used with this engine."
  18754.     ^shader! !
  18755.  
  18756. !B3DRenderEngine methodsFor: 'private-access' stamp: 'ar 4/17/1999 23:12'!
  18757. getTransformer
  18758.     "Private. Return the transformer used with this engine."
  18759.     ^transformer! !
  18760.  
  18761. !B3DRenderEngine methodsFor: 'private-access' stamp: 'ar 4/17/1999 23:11'!
  18762. getVertexBuffer
  18763.     "Private. Return the vertex buffer used with this engine."
  18764.     ^vertexBuffer! !
  18765.  
  18766. !B3DRenderEngine methodsFor: 'private-access' stamp: 'ar 5/26/2000 15:19'!
  18767. target
  18768.     "Return the rendering target"
  18769.     ^rasterizer target! !
  18770.  
  18771. !B3DRenderEngine methodsFor: 'private-access' stamp: 'ar 5/26/2000 15:19'!
  18772. target: aForm
  18773.     "Set the rendering target"
  18774.     ^rasterizer target: aForm! !
  18775.  
  18776. !B3DRenderEngine methodsFor: 'private-access' stamp: 'ar 5/26/2000 15:18'!
  18777. viewportOffset
  18778.     "Return the offset for the viewport"
  18779.     ^rasterizer viewportOffset! !
  18780.  
  18781. !B3DRenderEngine methodsFor: 'private-access' stamp: 'ar 5/26/2000 15:16'!
  18782. viewportOffset: aPoint
  18783.     "Set the offset for the viewport"
  18784.     ^rasterizer viewportOffset: aPoint! !
  18785.  
  18786. !B3DRenderEngine methodsFor: 'picking' stamp: 'ar 4/18/1999 02:28'!
  18787. asPickerAt: aPoint
  18788.     ^self asPickerAt: aPoint extent: 1@1! !
  18789.  
  18790. !B3DRenderEngine methodsFor: 'picking' stamp: 'ar 4/17/1999 23:56'!
  18791. asPickerAt: aPoint extent: extentPoint
  18792.     | picker |
  18793.     picker _ B3DPickerEngine new.
  18794.     picker loadFrom: self.
  18795.     picker pickAt: aPoint extent: extentPoint.
  18796.     ^picker! !
  18797.  
  18798. !B3DRenderEngine methodsFor: 'picking' stamp: 'ar 2/27/2000 20:12'!
  18799. pickingMatrixAt: aPoint extent: extentPoint
  18800.     "Return a matrix for picking at the given point using the given extent."
  18801.     ^self pickingMatrixFor: self viewport at: aPoint extent: extentPoint! !
  18802.  
  18803. !B3DRenderEngine methodsFor: 'picking' stamp: 'ar 2/27/2000 20:10'!
  18804. pickingMatrixFor: vp at: aPoint extent: extentPoint
  18805.     "Return a matrix for picking at the given point using the given extent."
  18806.     | m scaleX scaleY ofsX ofsY |
  18807.     scaleX _ vp width / extentPoint x.
  18808.     scaleY _ vp height / extentPoint y.
  18809.     ofsX _ (vp width + (2.0 * (vp origin x - aPoint x))) / extentPoint x.
  18810.     ofsY _ (vp height + (2.0 * (aPoint y - vp corner y))) / extentPoint y.
  18811.     m _ B3DMatrix4x4 identity.
  18812.     m a11: scaleX; a22: scaleY.
  18813.     m a14: ofsX; a24: ofsY.
  18814.     ^m! !
  18815.  
  18816. !B3DRenderEngine methodsFor: 'properties' stamp: 'ar 11/7/1999 18:23'!
  18817. hasProperty: propName
  18818.     "Answer whether the receiver has the given property.  Deemed to have it only if I have a property dictionary entry for it and that entry is neither nil nor false"
  18819.     self valueOfProperty: propName ifAbsent:[^false].
  18820.     ^true! !
  18821.  
  18822. !B3DRenderEngine methodsFor: 'properties' stamp: 'ar 11/7/1999 18:25'!
  18823. properties
  18824.     ^properties ifNil:[properties _ IdentityDictionary new].! !
  18825.  
  18826. !B3DRenderEngine methodsFor: 'properties' stamp: 'ar 11/7/1999 18:23'!
  18827. removeProperty: propName
  18828.     self valueOfProperty: propName ifAbsent:[^self].
  18829.     self properties removeKey: propName.! !
  18830.  
  18831. !B3DRenderEngine methodsFor: 'properties' stamp: 'ar 11/7/1999 18:22'!
  18832. setProperty: propName toValue: aValue
  18833.  
  18834.     aValue ifNil: [^ self removeProperty: propName].
  18835.     self properties at: propName put: aValue.! !
  18836.  
  18837. !B3DRenderEngine methodsFor: 'properties' stamp: 'ar 11/7/1999 18:24'!
  18838. valueOfProperty: propName
  18839.     ^self valueOfProperty: propName ifAbsent:[nil]! !
  18840.  
  18841. !B3DRenderEngine methodsFor: 'properties' stamp: 'ar 11/7/1999 18:36'!
  18842. valueOfProperty: propName ifAbsent: aBlock
  18843.     properties == nil ifTrue: [^ aBlock value].
  18844.     ^properties at: propName ifAbsent: aBlock! !
  18845.  
  18846. !B3DRenderEngine class methodsFor: 'instance creation' stamp: 'ar 5/26/2000 15:10'!
  18847. defaultForPlatformOn: aForm
  18848.     "Return the render engine that is most appropriate for the current host platform."
  18849.     (B3DHardwareEngine isAvailableFor: aForm) 
  18850.         ifTrue:[^B3DHardwareEngine newOn: aForm].
  18851.     (B3DPrimitiveEngine isAvailableFor: aForm) 
  18852.         ifTrue:[^B3DPrimitiveEngine newOn: aForm].
  18853.     ^B3DRenderEngine newOn: aForm! !
  18854.  
  18855. !B3DRenderEngine class methodsFor: 'instance creation'!
  18856. new
  18857.     ^super new initialize! !
  18858.  
  18859. !B3DRenderEngine class methodsFor: 'instance creation' stamp: 'ar 5/26/2000 15:49'!
  18860. newOn: aForm
  18861.     ^(self new) target: aForm; yourself! !
  18862.  
  18863. !B3DRenderEngine class methodsFor: 'accessing' stamp: 'ar 2/14/1999 01:37'!
  18864. clipper
  18865.     "Return the transformer to use with this engine"
  18866.     ^B3DVertexClipper! !
  18867.  
  18868. !B3DRenderEngine class methodsFor: 'accessing' stamp: 'ar 4/18/1999 05:27'!
  18869. rasterizer
  18870.     "Return the rasterizer to use with this engine"
  18871.     ^B3DSimulRasterizer! !
  18872.  
  18873. !B3DRenderEngine class methodsFor: 'accessing' stamp: 'ar 2/14/1999 01:37'!
  18874. shader
  18875.     "Return the shader to use with this engine"
  18876.     ^B3DVertexShader! !
  18877.  
  18878. !B3DRenderEngine class methodsFor: 'accessing' stamp: 'ar 2/14/1999 01:37'!
  18879. transformer
  18880.     "Return the transformer to use with this engine"
  18881.     ^B3DVertexTransformer! !
  18882.  
  18883. !B3DRenderEngine class methodsFor: 'testing' stamp: 'ar 2/14/1999 01:39'!
  18884. isAvailable
  18885.     "Return true if this engine is available (e.g., all of its parts are avaiable)"
  18886.     ^(self transformer isAvailable and:[
  18887.         self shader isAvailable and:[
  18888.             self clipper isAvailable and:[
  18889.                 self rasterizer isAvailable]]])! !
  18890.  
  18891. !B3DRenderEngine class methodsFor: 'testing' stamp: 'ar 2/16/1999 17:34'!
  18892. isAvailableFor: anOutputMedium
  18893.     "Return true if this engine is available for the given output medium"
  18894.     ^(self transformer isAvailableFor: anOutputMedium)  and:[
  18895.         (self shader isAvailableFor: anOutputMedium) and:[
  18896.             (self clipper isAvailableFor: anOutputMedium) and:[
  18897.                 (self rasterizer isAvailableFor: anOutputMedium)]]]! !
  18898.  
  18899. I represent general 3d rotations by using Unit-Quaternions. Unit-Quaternions are one of the best available representation for rotations in computer graphics because they provide an easy way of doing arithmetic with them and also because they allow us to use spherical linear interpolation (so-called "slerps") of rotations.
  18900.  
  18901. Indexed Variables:
  18902.     a    <Float>    the real part of the quaternion
  18903.     b    <Float>    the first imaginary part of the quaternion
  18904.     c    <Float>    the second imaginary part of the quaternion
  18905.     d    <Float>    the third imaginary part of the quaternion
  18906.  
  18907. !
  18908. !B3DRotation methodsFor: 'initialize' stamp: 'ar 2/1/1999 22:02'!
  18909. a: aValue b: bValue c: cValue d: dValue
  18910.  
  18911.     self a: aValue.
  18912.     self b: bValue.
  18913.     self c: cValue.
  18914.     self d: dValue.
  18915.     (aValue < 0.0) ifTrue:[self *= -1.0].
  18916.     self normalize.! !
  18917.  
  18918. !B3DRotation methodsFor: 'initialize' stamp: 'ar 2/1/1999 22:02'!
  18919. angle: anAngle axis: aVector3
  18920.  
  18921.     self radiansAngle: anAngle degreesToRadians axis: aVector3
  18922. ! !
  18923.  
  18924. !B3DRotation methodsFor: 'initialize' stamp: 'ar 2/1/1999 22:02'!
  18925. from: startVector to: endVector
  18926.     "Create a rotation from startVector to endVector"
  18927.     | axis cos sin |
  18928.     axis := startVector cross: endVector.
  18929.     cos := (startVector dot: endVector) arcCos.
  18930.     sin := axis length.
  18931.     axis safelyNormalize.
  18932.     self a: cos b: axis x * sin c: axis y * sin d: axis z * sin. ! !
  18933.  
  18934. !B3DRotation methodsFor: 'initialize' stamp: 'ar 2/1/1999 22:03'!
  18935. radiansAngle: anAngle axis: aVector3
  18936.  
  18937.     | angle sin cos |
  18938.     angle := anAngle / 2.0.
  18939.     cos := angle cos.
  18940.     sin := angle sin.
  18941.     self a: cos b: aVector3 x * sin c: aVector3 y * sin d: aVector3 z * sin.! !
  18942.  
  18943. !B3DRotation methodsFor: 'initialize'!
  18944. setIdentity
  18945.     ^self loadFrom: B3DIdentityRotation! !
  18946.  
  18947. !B3DRotation methodsFor: 'initialize' stamp: 'ar 2/1/1999 22:03'!
  18948. x: xValue y: yValue z: zValue a: anAngle
  18949.  
  18950.     | angle sin cos |
  18951.     angle := (anAngle degreesToRadians) / 2.0.
  18952.     cos := angle cos.
  18953.     sin := angle sin.
  18954.     self a: cos b: xValue * sin c: yValue * sin d: zValue * sin! !
  18955.  
  18956. !B3DRotation methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:59'!
  18957. a
  18958.     ^self at: 1! !
  18959.  
  18960. !B3DRotation methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:59'!
  18961. a: aFloat
  18962.     self at: 1 put: aFloat! !
  18963.  
  18964. !B3DRotation methodsFor: 'accessing' stamp: 'ar 2/1/1999 22:04'!
  18965. angle
  18966.     ^(self a arcCos * 2.0 radiansToDegrees)! !
  18967.  
  18968. !B3DRotation methodsFor: 'accessing'!
  18969. angle: newAngle
  18970.     self angle: newAngle axis: self axis! !
  18971.  
  18972. !B3DRotation methodsFor: 'accessing'!
  18973. axis
  18974.     | sinAngle |
  18975.     sinAngle := self a arcCos sin.
  18976.     sinAngle isZero ifTrue:[^B3DVector3 zero].
  18977.     ^B3DVector3 
  18978.         x: (self b / sinAngle)
  18979.         y: (self c / sinAngle)
  18980.         z: (self d / sinAngle)! !
  18981.  
  18982. !B3DRotation methodsFor: 'accessing'!
  18983. axis: newAxis
  18984.     self angle: self angle axis: newAxis! !
  18985.  
  18986. !B3DRotation methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:59'!
  18987. b
  18988.     ^self at: 2! !
  18989.  
  18990. !B3DRotation methodsFor: 'accessing' stamp: 'ar 2/1/1999 22:00'!
  18991. b: aFloat
  18992.     self at: 2 put: aFloat! !
  18993.  
  18994. !B3DRotation methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:59'!
  18995. c
  18996.     ^self at: 3! !
  18997.  
  18998. !B3DRotation methodsFor: 'accessing' stamp: 'ar 2/1/1999 22:00'!
  18999. c: aFloat
  19000.     self at: 3 put: aFloat! !
  19001.  
  19002. !B3DRotation methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:59'!
  19003. d
  19004.     ^self at: 4! !
  19005.  
  19006. !B3DRotation methodsFor: 'accessing' stamp: 'ar 2/1/1999 22:00'!
  19007. d: aFloat
  19008.     self at: 4 put: aFloat! !
  19009.  
  19010. !B3DRotation methodsFor: 'arithmetic' stamp: 'ar 2/1/1999 22:05'!
  19011. * aRotation
  19012.     "Multiplying two rotations is the same as concatenating the two rotations."
  19013.     | v1 v2 v3 vv |
  19014.     v1 := self bcd * aRotation a.
  19015.     v2 := aRotation bcd * self a.
  19016.     v3 := aRotation bcd cross: self bcd.
  19017.     vv := v1 + v2 + v3.
  19018.     ^B3DRotation
  19019.         a: (self a * aRotation a) - (self bcd dot: aRotation bcd)
  19020.         b: vv x
  19021.         c: vv y
  19022.         d: vv z! !
  19023.  
  19024. !B3DRotation methodsFor: 'arithmetic' stamp: 'ar 2/1/1999 22:06'!
  19025. negated
  19026.     "Negating a quaternion is the same as reversing the angle of rotation"
  19027.     ^B3DRotation
  19028.         a: self a negated
  19029.         b: self b
  19030.         c: self c
  19031.         d: self d! !
  19032.  
  19033. !B3DRotation methodsFor: 'arithmetic' stamp: 'ar 9/17/1999 12:43'!
  19034. normalize
  19035.     "Normalize the receiver. Note that the actual angle (a) determining the amount of 
  19036.     rotation is fixed, since we do not want to modify angles. This leads to:
  19037.         a^2 + b^2 + c^2 + d^2 = 1.
  19038.         b^2 + c^2 + d^2 = 1 - a^2.
  19039.     Note also that the angle (a) can not exceed 1.0 (due its creation by cosine) and
  19040.     if it is 1.0 we have exactly the unit quaternion ( 1, [ 0, 0, 0]).
  19041.     "
  19042.     | oneMinusASquared length |
  19043.     oneMinusASquared := 1.0 - (self a squared).
  19044.     (oneMinusASquared < 1.0e-10) ifTrue:[^self setIdentity].
  19045.     length := ((self b squared + self c squared + self d squared) / oneMinusASquared) sqrt.
  19046.     length = 0.0 ifTrue:[^self setIdentity].
  19047.     self b: self b / length.
  19048.     self c: self c / length.
  19049.     self d: self d / length.
  19050. ! !
  19051.  
  19052. !B3DRotation methodsFor: 'converting'!
  19053. asMatrix4x4
  19054.     "Given a quaternion q = (a, [ b, c , d]) the rotation matrix can be calculated as
  19055.             |    1 -    2(cc+dd),        2(bc-da),        2(db+ca)    |
  19056.         m =    |        2(bc+da),    1 -     2(bb+dd),        2(cd-ba)        |
  19057.             |        2(db-ca),        2(cd+ba),    1 -    2(bb+cc)    |
  19058.     "
  19059.     | a b c d m bb cc dd bc cd db ba ca da |
  19060.     a _ self a. b _ self b. c _ self c. d _ self d.
  19061.     bb := (b * b).    cc := (c * c).    dd := (d * d).
  19062.     bc := (b * c).    cd := (c * d).    db := (d * b).
  19063.     ba := (b * a).    ca := (c * a).    da := (d * a).
  19064.     m := self matrixClass identity.
  19065.     m 
  19066.         a11: 1.0 - (cc + dd * 2.0);a12: (bc - da * 2.0);         a13: (db + ca * 2.0);
  19067.         a21: (bc + da * 2.0);        a22: 1.0 - (bb + dd * 2.0);a23: (cd - ba * 2.0);
  19068.         a31: (db - ca * 2.0);        a32: (cd + ba * 2.0);        a33: 1.0 - (bb + cc * 2.0).
  19069.     ^m
  19070. ! !
  19071.  
  19072. !B3DRotation methodsFor: 'converting' stamp: 'ar 2/1/1999 22:08'!
  19073. normalized
  19074.     ^self copy normalize! !
  19075.  
  19076. !B3DRotation methodsFor: 'interpolating' stamp: 'jsp 2/25/1999 15:57'!
  19077. interpolateTo: aRotation at: t
  19078.     "Spherical linear interpolation (slerp) from the receiver to aQuaternion"
  19079.     ^self slerpTo: aRotation at: t extraSpins: 0! !
  19080.  
  19081. !B3DRotation methodsFor: 'interpolating' stamp: 'ar 2/1/1999 22:08'!
  19082. slerpTo: aRotation at: t
  19083.     "Spherical linear interpolation (slerp) from the receiver to aQuaternion"
  19084.     ^self slerpTo: aRotation at: t extraSpins: 0! !
  19085.  
  19086. !B3DRotation methodsFor: 'interpolating' stamp: 'ar 3/24/1999 14:58'!
  19087. slerpTo: aRotation at: t extraSpins: spin
  19088.     "Sperical Linear Interpolation (slerp).
  19089.     Calculate the new quaternion when applying slerp from the receiver (t = 0.0)
  19090.     to aRotation (t = 1.0). spin indicates the number of extra rotations to be added.
  19091.     The code shown below is from Graphics Gems III"
  19092.     | cosT alpha beta flip theta phi sinT |
  19093.     alpha := t.
  19094.     flip := false.
  19095.     "calculate the cosine of the two quaternions on the 4d sphere"
  19096.     cosT := self dot: aRotation.
  19097.     "if aQuaternion is on the opposite hemisphere reverse the direction
  19098.     (note that in quaternion space two points describe the same rotation)"
  19099.     cosT < 0.0 ifTrue:[
  19100.         flip := true.
  19101.         cosT := cosT negated].
  19102.     "If the aQuaternion is nearly the same as I am use linear interpolation"
  19103.     cosT > 0.99999 ifTrue:[
  19104.         "Linear Interpolation"
  19105.         beta := 1.0 - alpha
  19106.     ] ifFalse:[
  19107.         "Spherical Interpolation"
  19108.         theta := cosT arcCos.
  19109.         phi := (spin * Float pi) + theta.
  19110.         sinT := theta sin.
  19111.         beta := (theta - (alpha * phi)) sin / sinT.
  19112.         alpha := (alpha * phi) sin / sinT].
  19113.  
  19114.     flip ifTrue:[alpha := alpha negated].
  19115.     ^B3DRotation 
  19116.         a: (alpha * aRotation a) + (beta * self a)
  19117.         b: (alpha * aRotation b) + (beta * self b)
  19118.         c: (alpha * aRotation c) + (beta * self c)
  19119.         d: (alpha * aRotation d) + (beta * self d)! !
  19120.  
  19121. !B3DRotation methodsFor: 'printing' stamp: 'ar 2/1/1999 22:09'!
  19122. printOn: aStream
  19123.  
  19124.     aStream 
  19125.         nextPutAll: self class name;
  19126.         nextPut:$(;
  19127.         print: self angle;
  19128.         nextPut: Character space;
  19129.         print: self axis;
  19130.         nextPut:$).! !
  19131.  
  19132. !B3DRotation methodsFor: 'private'!
  19133. bcd
  19134.     ^B3DVector3 x: self b y: self c z: self d! !
  19135.  
  19136. !B3DRotation methodsFor: 'private' stamp: 'ar 2/1/1999 22:10'!
  19137. matrixClass
  19138.     ^B3DMatrix4x4! !
  19139.  
  19140. !B3DRotation class methodsFor: 'instance creation'!
  19141. a: aValue b: bValue c: cValue d: dValue
  19142.     ^self new a: aValue b: bValue c: cValue d: dValue! !
  19143.  
  19144. !B3DRotation class methodsFor: 'instance creation'!
  19145. angle: anAngle axis: aVector3
  19146.     ^self new angle: anAngle axis: aVector3! !
  19147.  
  19148. !B3DRotation class methodsFor: 'instance creation'!
  19149. axis: aVector3 angle: anAngle
  19150.     ^self angle: anAngle axis: aVector3! !
  19151.  
  19152. !B3DRotation class methodsFor: 'instance creation'!
  19153. from: startVector to: endVector
  19154.     ^self new from: startVector to: endVector! !
  19155.  
  19156. !B3DRotation class methodsFor: 'instance creation'!
  19157. identity
  19158.     ^self new setIdentity! !
  19159.  
  19160. !B3DRotation class methodsFor: 'instance creation' stamp: 'ar 2/1/1999 21:32'!
  19161. numElements
  19162.     ^4! !
  19163.  
  19164. !B3DRotation class methodsFor: 'instance creation'!
  19165. radiansAngle: anAngle axis: aVector3
  19166.     ^self new radiansAngle: anAngle axis: aVector3! !
  19167.  
  19168. !B3DRotation class methodsFor: 'instance creation'!
  19169. x: xValue y: yValue z: zValue a: anAngle
  19170.     ^self new x: xValue y: yValue z: zValue a: anAngle! !
  19171.  
  19172. !B3DRotation class methodsFor: 'class initialization'!
  19173. initialize
  19174.     "B3DRotation initialize"
  19175.     B3DIdentityRotation _ self new.
  19176.     B3DIdentityRotation floatAt: 1 put: 1.0.! !
  19177.  
  19178. !B3DRotationArray class methodsFor: 'instance creation' stamp: 'ar 5/4/2000 15:45'!
  19179. contentsClass
  19180.     ^B3DRotation! !
  19181.  
  19182. I represent a mesh from Autodesk 3D Studio.!
  19183. !B3DSTriangleMesh methodsFor: 'initialize' stamp: 'ar 2/7/1999 20:57'!
  19184. from3DS: aDictionary
  19185.     | triList triSpec triSize tri flags |
  19186.     aDictionary isEmpty ifTrue:[^nil].
  19187.     vertices _ aDictionary at: #vertexList.
  19188.     "matrix _ aDictionary at: #matrix ifAbsent:[nil].
  19189.     matrix ifNotNil:[matrix quickTransformV3ArrayFrom: vertices to: vertices]."
  19190.     vtxTexCoords _ aDictionary at: #textureVertices ifAbsent:[nil].
  19191.     triList _ aDictionary at: #triList.
  19192.     triSpec _ triList first.
  19193.     triSize _ triSpec size.
  19194.     faces _ B3DIndexedTriangleArray new: triSize.
  19195.     edgeFlags _ ByteArray new: triSize.
  19196.     1 to: triSize do:[:i|
  19197.         tri _ (triSpec at: i) key.
  19198.         flags _ (triSpec at: i) value.
  19199.         faces at: i put: (B3DIndexedTriangle with: tri first with: tri second with: tri third).
  19200.         edgeFlags at: i put: flags].
  19201.     triList second ifNotNil:[
  19202.         smoothFlags _ WordArray new: triSize.
  19203.         triList second doWithIndex:[:smoothFlag :index| smoothFlags at: index put: smoothFlag]].
  19204. ! !
  19205.  
  19206. !B3DSTriangleMesh methodsFor: 'private' stamp: 'ar 2/15/1999 06:44'!
  19207. collectSplitVertices: aSet
  19208.     "Collect the non smooth vertices into a Dictionary
  19209.         vertex index -> Dictionary
  19210.                             smoothing group -> list of face indexes.
  19211.     "
  19212.     | face flag vtxIndex groups groupDict |
  19213.     groupDict _ Dictionary new: aSet size * 2.
  19214.     1 to: faces size do:[:faceIndex|
  19215.         face _ faces at: faceIndex.
  19216.         flag _ smoothFlags at: faceIndex.
  19217.         1 to: 3 do:[:j|
  19218.             vtxIndex _ face at: j.
  19219.             (aSet includes: vtxIndex) ifTrue:[ 
  19220.                 groups _ groupDict at: vtxIndex ifAbsentPut:[Dictionary new].
  19221.                 (groups at: flag ifAbsentPut:[OrderedCollection new]) add: faceIndex.
  19222.             ].
  19223.         ].
  19224.     ].
  19225.     ^groupDict! !
  19226.  
  19227. !B3DSTriangleMesh methodsFor: 'private' stamp: 'ar 2/17/1999 15:59'!
  19228. computeFunkyVertexNormals
  19229.     "Compute the vertex normals for the receiver.
  19230.     Don't split the faces so we'll get some funky lighting effects."
  19231.     vtxNormals _ super computeVertexNormals
  19232. ! !
  19233.  
  19234. !B3DSTriangleMesh methodsFor: 'private' stamp: 'ar 2/17/1999 15:57'!
  19235. computeVertexNormals
  19236.     "Compute the vertex normals for the receiver.
  19237.     Note: This is a multi pass process here - we may have to split up vertices"
  19238.     | set dict |
  19239.     set _ self detectNonSmoothVertices.
  19240.     set isEmpty ifFalse:[
  19241.         "Collect the dictionary of vertices to split"
  19242.         dict _ self collectSplitVertices: set.
  19243.         "And actually split them"
  19244.         self splitVerticesFrom: dict.
  19245.     ].
  19246.     "Now do the actual computation"
  19247.     ^super computeVertexNormals! !
  19248.  
  19249. !B3DSTriangleMesh methodsFor: 'private' stamp: 'ar 2/15/1999 06:54'!
  19250. detectNonSmoothVertices
  19251.     "Detect all the vertices in the receiver that cannot be easily smoothed"
  19252.     | mask face flag vtxIndex out newMask |
  19253.     smoothFlags ifNil:[^#()].
  19254.     mask _ WordArray new: vertices size.
  19255.     mask atAllPut: 16rFFFFFFFF.
  19256.     out _ Set new: 1000. "Leave us enough space to avoid collisions"
  19257.     1 to: faces size do:[:i|
  19258.         face _ faces at: i.
  19259.         flag _ smoothFlags at: i.
  19260.         1 to: 3 do:[:j|
  19261.             vtxIndex _ face at: j.
  19262.             newMask _ ((mask at: vtxIndex) bitAnd: flag).
  19263.             newMask = 0 ifTrue:[out add: vtxIndex].
  19264.             mask at: vtxIndex put: newMask.
  19265.         ].
  19266.     ].
  19267.     ^out! !
  19268.  
  19269. !B3DSTriangleMesh methodsFor: 'private' stamp: 'ar 2/15/1999 06:49'!
  19270. splitVerticesFrom: aDictionary
  19271.     "Split the non smooth vertices from the Dictionary
  19272.         vertex index -> Dictionary
  19273.                             smoothing group -> list of face indexes.
  19274.     "
  19275.     | newVertices newColors newTexCoords nextIndex vtxIndex nValues skipAssoc faceList iFace |
  19276.     newVertices _ WriteStream with: vertices.
  19277.     vtxColors ifNotNil:[newColors _ WriteStream with: vtxColors].
  19278.     vtxTexCoords ifNotNil:[newTexCoords _ WriteStream with: vtxTexCoords].
  19279.     nextIndex _ vertices size.
  19280.     aDictionary associationsDo:[:vertexAssoc|
  19281.         vtxIndex _ vertexAssoc key.
  19282.         nValues _ vertexAssoc value size - 1.
  19283.         "We have to copy n values"
  19284.         newVertices next: nValues put: (vertices at: vtxIndex).
  19285.         newColors ifNotNil:[newColors next: nValues put: (vtxColors at: vtxIndex)].
  19286.         newTexCoords ifNotNil:[newTexCoords next: nValues put: (vtxTexCoords at: vtxIndex)].
  19287.         skipAssoc _ true. "Skip the first association - we can reuse the original vertex"
  19288.         vertexAssoc value associationsDo:[:smoothAssoc|
  19289.             skipAssoc ifFalse:[
  19290.                 faceList _ smoothAssoc value.
  19291.                 nextIndex _ nextIndex + 1.
  19292.                 faceList do:[:faceIndex|
  19293.                     iFace _ faces at: faceIndex.
  19294.                     1 to: 3 do:[:i| (iFace at: i) = vtxIndex ifTrue:[iFace at: i put: nextIndex]].
  19295.                     faces at: faceIndex put: iFace.
  19296.                 ].
  19297.             ].
  19298.             skipAssoc _ false.
  19299.         ].
  19300.     ].
  19301.     "Cleanup"
  19302.     vtxNormals _ nil. "Must be recomputed"
  19303.     vertices _ newVertices contents.
  19304.     newColors ifNotNil:[vtxColors _ newColors contents].
  19305.     newTexCoords ifNotNil:[vtxTexCoords _ newTexCoords contents].! !
  19306.  
  19307. !B3DSTriangleMesh class methodsFor: 'instance creation' stamp: 'ar 2/6/1999 21:26'!
  19308. from3DS: aDictionary
  19309.     ^self new from3DS: aDictionary! !
  19310.  
  19311. !B3DScanner methodsFor: 'initialize' stamp: 'ar 4/18/1999 07:59'!
  19312. initialize
  19313.     aet _ B3DActiveEdgeTable new.
  19314.     fillList _ B3DFillList new.
  19315.     added _ B3DPrimitiveEdgeList new.
  19316.     lastIntersection _ B3DPrimitiveEdge new.
  19317.     nextIntersection _ B3DPrimitiveEdge new.
  19318.     objects _ OrderedCollection new.! !
  19319.  
  19320. !B3DScanner methodsFor: 'initialize' stamp: 'ar 4/18/1999 05:21'!
  19321. setupObjects
  19322.     "Set up the list of objects (e.g., triangle inputs)
  19323.     by creating a linked list of objects which is sorted by the initial
  19324.     yValue of the tris."
  19325.     | lastObj |
  19326.     objects _ objects sortBy: [:obj1 :obj2| obj1 bounds origin sortsBefore: obj2 bounds origin].
  19327.     lastObj _ nil.
  19328.     objects do:[:nextObj|
  19329.         nextObj reset.
  19330.         nextObj prevObj: lastObj.
  19331.         lastObj == nil ifFalse:[lastObj nextObj: nextObj].
  19332.         lastObj _ nextObj.
  19333.     ].
  19334.     lastObj == nil ifFalse:[lastObj nextObj: nil].
  19335. ! !
  19336.  
  19337. !B3DScanner methodsFor: 'public' stamp: 'ar 4/18/1999 05:15'!
  19338. addObject: primObj
  19339.     objects add: primObj.! !
  19340.  
  19341. !B3DScanner methodsFor: 'public' stamp: 'ar 4/18/1999 05:29'!
  19342. bitBlt: aBitBlt
  19343.     bitBlt _ aBitBlt.! !
  19344.  
  19345. !B3DScanner methodsFor: 'public' stamp: 'ar 4/18/1999 07:55'!
  19346. mainLoop
  19347.     | yValue nextObjY nextEdgeY obj activeStart passiveStart scaledY |
  19348.     objects size = 0 ifTrue:[^self]. "No input"
  19349.     self setupObjects. "Sort objects and create linked list"
  19350.     nFaces _ maxFaces _ maxEdges _ 0.
  19351.     "Pre-fetch first object to start from"
  19352.     activeStart _ passiveStart _ objects at: 1.
  19353.     yValue _ nextEdgeY _ nextObjY _ passiveStart bounds origin y.
  19354.     [activeStart == nil and:[passiveStart == nil and:[aet isEmpty]]] whileFalse:[
  19355.         "Add new objects if necessary"
  19356.         yValue = nextObjY ifTrue:[
  19357.             "Make sure we add edges from newly created objects"
  19358.             nextEdgeY _ nextObjY.
  19359.             "Add new objects"
  19360.             [passiveStart notNil and:[passiveStart bounds origin y = nextObjY]]
  19361.                 whileTrue:[passiveStart _ passiveStart nextObj].
  19362.             passiveStart == nil 
  19363.                 ifTrue:[nextObjY _ 99999]"Some large value"
  19364.                 ifFalse:[nextObjY _ passiveStart bounds origin y]. 
  19365.         ]. "End of adding new objects"
  19366.  
  19367.         "Add new edges if necessary"
  19368.         yValue = nextEdgeY ifTrue:[
  19369.             nextEdgeY _ nextObjY bitShift: 12. "Some VERY large value"
  19370.             scaledY _ (yValue+1) bitShift: 12.
  19371.             obj _ activeStart.
  19372.             [obj == passiveStart] whileFalse:[
  19373.                 [obj atEnd not and:[obj peekY < scaledY]]
  19374.                     whileTrue:[self addEdgesFromFace: obj next at: yValue].
  19375.                 obj atEnd ifTrue:[
  19376.                     obj == activeStart
  19377.                         ifTrue:[activeStart _ obj nextObj]
  19378.                         ifFalse:[obj prevObj nextObj: obj nextObj].
  19379.                 ] ifFalse:[obj peekY < nextEdgeY ifTrue:[nextEdgeY _ obj peekY]].
  19380.                 obj _ obj nextObj.
  19381.             ].
  19382.             nextEdgeY _ (nextEdgeY bitShift: -12).
  19383.         ].
  19384.         added isEmpty ifFalse:[
  19385.             "Merge new edges into AET"
  19386.             "Note: These may be lower half edges."
  19387.             B3DScanner doDebug ifTrue:[self validateAETOrder].
  19388.             aet mergeEdgesFrom: added.
  19389.             B3DScanner doDebug ifTrue:[
  19390.                 self validateAETOrder.
  19391.                 self validateEdgesFrom: aet].
  19392.             added reset. "Clean up the list"
  19393.         ].
  19394.  
  19395.         "This is the core loop."
  19396.         "[yValue < nextEdgeY and:[added isEmpty and:[aet isEmpty not]]] whileTrue:["
  19397.             B3DScanner doDebug ifTrue:[yValue printString displayAt: 0@0].
  19398.             "gather stats"
  19399.             maxEdges _ maxEdges max: aet size.
  19400.             maxFaces _ maxFaces max: nFaces.
  19401.  
  19402.             "Scan out the AET"
  19403.             aet isEmpty ifFalse:[
  19404.                 self clearSpanBufferAt: yValue.
  19405.                 self scanAETAt: yValue.
  19406.                 self drawSpanBufferAt: yValue.
  19407.  
  19408.                 "Advance to next y and update AET"
  19409.             ].
  19410.             yValue _ yValue + 1.
  19411.             aet isEmpty ifFalse:[self updateAETAt: yValue].
  19412.         "]."
  19413.     ].
  19414.     nFaces = 0 ifFalse:[self error: nFaces printString,' remaining faces'].! !
  19415.  
  19416. !B3DScanner methodsFor: 'public' stamp: 'ar 4/18/1999 05:31'!
  19417. resetObjects
  19418.     objects _ OrderedCollection new.! !
  19419.  
  19420. !B3DScanner methodsFor: 'public' stamp: 'ar 4/18/1999 05:28'!
  19421. spanBuffer: aBitmap
  19422.     spanBuffer _ aBitmap.! !
  19423.  
  19424. !B3DScanner methodsFor: 'aet adding' stamp: 'ar 4/18/1999 08:14'!
  19425. addEdgesFromFace: face at: yValue
  19426.     "Add the two top edges from the given face to the aet.
  19427.     The top edges are (v0-v1) and (v0-v2) where (v0-v1) is 
  19428.     the 'upper' half-edge of the triangle"
  19429.     | xValue index needMajor needMinor majorEdge minorEdge |
  19430.     face oneOverArea = 0.0 ifTrue:[^self].
  19431.     needMinor _ needMajor _ true. "We need both edges"
  19432.     majorEdge _ minorEdge _ nil.
  19433.     xValue _ face vertex0 windowPosX.
  19434.     "Search the insertion list to merge the edges of the face"
  19435.     index _ added firstIndexForInserting: xValue.
  19436.     index _ added xValue: xValue from: index do:[:edge|
  19437.         (edge rightFace == nil and:[
  19438.             "Note: edge vertex0 == face vertex0 should be the case for most meshes.
  19439.                 But since it is advantegous for the scanner to have two faces per edge
  19440.                 we're also checking for the actual vertex values."
  19441.             edge vertex0 == face vertex0 or:[
  19442.                 edge vertex0 rasterPos = face vertex0 rasterPos]]) ifTrue:[
  19443.             "This edge is a possible candidate for adding the face"
  19444.             (needMajor and:["See above comment"
  19445.                 edge vertex1 == face vertex2 or:[
  19446.                     edge vertex1 rasterPos = face vertex2 rasterPos]]) ifTrue:[
  19447.                 majorEdge _ edge.
  19448.                 edge rightFace: face.
  19449.                 edge flags: (edge flags bitOr: FlagEdgeRightMajor).
  19450.                 nFaces _ nFaces + 1.
  19451.                 needMinor ifFalse:[
  19452.                     ^self adjustFace: face major: majorEdge minor: minorEdge]. "Done."
  19453.                 needMajor _ false.
  19454.             ] ifFalse:[
  19455.                 (needMinor and:["See above comment"
  19456.                     edge vertex1 == face vertex1 or:[
  19457.                         edge vertex1 rasterPos = face vertex1 rasterPos]]) ifTrue:[
  19458.                     minorEdge _ edge.
  19459.                     edge rightFace: face.
  19460.                     edge flags: (edge flags bitOr: FlagContinueRightEdge).
  19461.                     needMajor ifFalse:[
  19462.                         ^self adjustFace: face major: majorEdge minor: minorEdge]. "Done."
  19463.                     needMinor _ false.
  19464.                 ].
  19465.             ].
  19466.         ].
  19467.     ].
  19468.     "Need to add new edges.
  19469.     NOTE: index already points to the right point for insertion."
  19470.     needMajor ifTrue:[
  19471.         majorEdge _ B3DPrimitiveEdge new.
  19472.         majorEdge v0: face vertex0 v1: face vertex2.
  19473.         majorEdge nLines = 0 ifTrue:[^self]. "Horizontal edge"
  19474.         majorEdge leftFace: face.
  19475.         majorEdge initializePass1.
  19476.         majorEdge flags: (majorEdge flags bitOr: FlagEdgeLeftMajor).
  19477.         nFaces _ nFaces + 1.
  19478.     ].
  19479.     needMinor ifTrue:[
  19480.         minorEdge _ B3DPrimitiveEdge new.
  19481.         minorEdge v0: face vertex0 v1: face vertex1.
  19482.         minorEdge leftFace: face.
  19483.         minorEdge flags: FlagContinueLeftEdge.
  19484.  
  19485.         "Note: If the (upper) minor edge is horizontal, use the lower one.
  19486.         Note: The lower minor edge cannot be horizontal if the major one isn't"
  19487.         minorEdge nLines = 0 ifTrue:[
  19488.             needMajor ifTrue:[added add: majorEdge beforeIndex: index].
  19489.             minorEdge _ self addLowerEdge: minorEdge fromFace: face.
  19490.             minorEdge nLines = 0 ifTrue:[self error:'Minor edge is horizontal'].
  19491.             ^self adjustFace: face major: majorEdge minor: minorEdge].
  19492.  
  19493.         minorEdge flags: FlagContinueLeftEdge.
  19494.         minorEdge initializePass1.
  19495.         minorEdge xValue = xValue ifFalse:[self error:'Problem with minor edge'].
  19496.         minorEdge nLines = 0 ifTrue:[self error:'Minor edge is horizontal'].
  19497.     ].
  19498.     needMajor & needMinor ifTrue:[
  19499.         added add: majorEdge and: minorEdge beforeIndex: index.
  19500.     ] ifFalse:[
  19501.         needMajor
  19502.             ifTrue:[added add: majorEdge beforeIndex: index]
  19503.             ifFalse:[added add: minorEdge beforeIndex: index].
  19504.     ].
  19505.     ^self adjustFace: face major: majorEdge minor: minorEdge.! !
  19506.  
  19507. !B3DScanner methodsFor: 'aet adding' stamp: 'ar 4/18/1999 05:56'!
  19508. addLowerEdge: oldEdge fromFace: face
  19509.     "Add the lower edge (v1-v2) from the given face.
  19510.     Return the newly created edge."
  19511.     | index minorEdge xValue |
  19512.     xValue _ face vertex1 windowPosX.
  19513.     index _ added firstIndexForInserting: xValue.
  19514.     index _ added xValue: xValue from: index do:[:edge|
  19515.         (edge rightFace == nil and:[
  19516.             "See the comment in #addEdgesFromFace:at:"
  19517.             (edge vertex0 == face vertex1 and:[edge vertex1 == face vertex2]) or:[
  19518.             edge vertex0 rasterPos = face vertex1 rasterPos and:[
  19519.                 edge vertex1 rasterPos = face vertex2 rasterPos]]]) ifTrue:[
  19520.                 "Adjust the left or right edge of the face"
  19521.                 face leftEdge == oldEdge
  19522.                     ifTrue:[face leftEdge: edge]
  19523.                     ifFalse:[face rightEdge: edge].
  19524.                 edge rightFace: face.
  19525.                 ^edge
  19526.             ].
  19527.     ].
  19528.     "Need to add new edge.
  19529.     NOTE: index already points to the right point for insertion."
  19530.     minorEdge _ B3DPrimitiveEdge new.
  19531.     minorEdge v0: face vertex1 v1: face vertex2.
  19532.     minorEdge nLines = 0 ifTrue:[^self]. "Horizontal"
  19533.     "Adjust left/right edge of the face"
  19534.     face leftEdge == oldEdge
  19535.         ifTrue:[face leftEdge: minorEdge]
  19536.         ifFalse:[face rightEdge: minorEdge].
  19537.     minorEdge leftFace: face.
  19538.     minorEdge initializePass1.
  19539.     added add: minorEdge beforeIndex: index.
  19540.     ^minorEdge! !
  19541.  
  19542. !B3DScanner methodsFor: 'aet adding' stamp: 'ar 4/8/1999 03:02'!
  19543. adjustFace: face major: majorEdge minor: minorEdge
  19544.     "Set the left/right edge of the face to the appropriate edges"
  19545.     (majorEdge == nil or:[minorEdge == nil]) 
  19546.         ifTrue:[^self error:'Edges must be non-nil'].
  19547.     majorEdge xValue = minorEdge xValue ifTrue:[
  19548.         "Most likely case. Both edges start at the same point.
  19549.         Use dx/dy slope for determining which one is left and which one is right.
  19550.         NOTE:     We have this already computed during face>>initializePass1.
  19551.                 The value to use is the x increment at each scan line.
  19552.         NOTE2:     There is also a border case when minorEdge is actually the lower
  19553.                 edge of the triangle. If both xValues are equal, then the triangle
  19554.                 is degenerate (e.g., it's area is zero) in which case the meaning of
  19555.                 'left' or 'right' does not matter at all (and can thus be handled
  19556.                 by this simple test)."
  19557.         majorEdge xIncrement <= minorEdge xIncrement
  19558.             ifTrue:[    face leftEdge: majorEdge.
  19559.                     face rightEdge: minorEdge]
  19560.             ifFalse:[    face leftEdge: minorEdge.
  19561.                     face rightEdge: majorEdge].
  19562.     ] ifFalse:[
  19563.         "If the x values are not equal, simply use the edge with the smaller x value as 'left' edge"
  19564.         majorEdge xValue < minorEdge xValue 
  19565.             ifTrue:[    face leftEdge: majorEdge.
  19566.                     face rightEdge: minorEdge]
  19567.             ifFalse:[    face leftEdge: minorEdge.
  19568.                     face rightEdge: majorEdge].
  19569.     ].! !
  19570.  
  19571. !B3DScanner methodsFor: 'aet scanning' stamp: 'ar 4/18/1999 05:57'!
  19572. adjustIntersectionsAt: yValue from: topEdge
  19573.     "The top face has changed. Adjust for possible intersections in the same scan line."
  19574.     | frontFace backFace |
  19575.     frontFace _ fillList first.
  19576.  
  19577.     "If frontFace is nil then the fillList is empty.
  19578.     If frontFace nextFace is nil then there is only one face in the list."
  19579.     (frontFace == nil or:[frontFace nextFace == nil]) ifTrue:[^self].
  19580.  
  19581.     "Now, search the fill list until we reach the first face with minZ > face maxZ.
  19582.     Note that we have a linked list and can thus start from frontFace nextFace 
  19583.     until we reach the end of the face list (nil)."
  19584.     backFace _ frontFace nextFace.
  19585.     [backFace == nil] whileFalse:[
  19586.         (self checkIntersectionOf: frontFace with: backFace at: yValue edge: topEdge)
  19587.             ifFalse:[^self]. "Aborted."
  19588.         backFace _ backFace nextFace.
  19589.     ].! !
  19590.  
  19591. !B3DScanner methodsFor: 'aet scanning' stamp: 'ar 4/13/1999 01:00'!
  19592. checkIntersectionOf: frontFace with: backFace at: yValue edge: leftEdge
  19593.     "Compute the possible intersection of frontFace and backFace at the given y value.
  19594.     Store the earliest intersection in nextIntersection. Return false if the face enumeration
  19595.     should be aborted, true otherwise. leftEdge is the edge defining the left-most boundary
  19596.     for possible intersections (e.g., all intersections have to be >= leftEdge xValue)"
  19597.     | floatX floatY frontZ backZ xValue rightX |
  19598.     backFace minZ >= frontFace maxZ ifTrue:[^false]. "Abort. Everything behind will be further away."
  19599.     "Check for shared edge of faces"
  19600.     frontFace leftEdge == backFace leftEdge ifTrue:[^true]. "Proceed."
  19601.     frontFace rightEdge == backFace rightEdge ifTrue:[^true]. "Proceed."
  19602.  
  19603.     "Check for newly created front face"
  19604.     (frontFace leftEdge xValue bitShift: -12) = 
  19605.         (frontFace rightEdge xValue bitShift: -12) ifTrue:[^false]. "Abort"
  19606.     "Check for newly created back face"
  19607.     (backFace leftEdge xValue bitShift: -12) = 
  19608.         (backFace rightEdge xValue bitShift: -12) ifTrue:[^true]. "Proceed"
  19609.  
  19610.     "Compute the z value of either frontFace or backFace depending on whose
  19611.     right edge x value is less (so we test a point that is inside both faces)"
  19612.     floatY _ yValue.
  19613.     frontFace rightEdge xValue <= backFace rightEdge xValue ifTrue:[
  19614.         "Use frontFace rightEdge as reference value"
  19615.         frontZ _ frontFace rightEdge zValue.
  19616.         rightX _ frontFace rightEdge xValue.
  19617.         floatX _ rightX / 4096.0.
  19618.         backZ _ backFace zValueAtX: floatX y: floatY.
  19619.     ] ifFalse:[
  19620.         "Use backFace rightEdge as reference value"
  19621.         backZ _ backFace rightEdge zValue.
  19622.         rightX _ backFace rightEdge xValue.
  19623.         floatX _ rightX / 4096.0.
  19624.         frontZ _ frontFace zValueAtX: floatX y: floatY.
  19625.     ].
  19626.     backZ < frontZ ifTrue:[
  19627.         "Found a possible intersection."
  19628.         xValue _ self computeIntersectionOf: frontFace with: backFace at: yValue ifError: leftEdge xValue.
  19629.         "The following tests for numerical inaccuracies"
  19630.         xValue > rightX ifTrue:[xValue _ rightX].
  19631.         xValue < leftEdge xValue ifTrue:[
  19632.             "In theory, this cannot happen. We may, however, have slight
  19633.             numerical inaccuracies here, too. Conceptually, we treat these
  19634.             intersections as if they occured immediately at the same 
  19635.             fractional pixel in the scan line."
  19636.             xValue _ leftEdge xValue].
  19637.         (xValue bitShift: -12) = (leftEdge xValue bitShift: -12) ifTrue:[
  19638.             "Intersections at the same pixel are ignored. Process it at the next pixel.
  19639.             NOTE: This step is incredibly important!! It is by ignoring intersections
  19640.             at the same pixel that we can never run in an endless repetition of
  19641.             intersections at the same pixel value."
  19642.             xValue _ (leftEdge xValue bitShift: -12) + 1 bitShift: 12.
  19643.         ].
  19644.         xValue < nextIntersection xValue ifTrue:[
  19645.             nextIntersection xValue: xValue.
  19646.             nextIntersection leftFace: frontFace.
  19647.             nextIntersection rightFace: backFace.
  19648.         ].
  19649.     ].
  19650.     ^true "proceed"! !
  19651.  
  19652. !B3DScanner methodsFor: 'aet scanning' stamp: 'ar 4/8/1999 03:14'!
  19653. computeIntersectionOf: frontFace with: backFace at: yValue ifError: errorValue
  19654.     "Compute the z intersection at the given y value"
  19655.     | dx1 dz1 dx2 dz2 px pz det det2 |
  19656.     dx1 _ frontFace rightEdge xValue - frontFace leftEdge xValue.
  19657.     dz1 _ frontFace rightEdge zValue - frontFace leftEdge zValue.
  19658.     dx2 _ backFace rightEdge xValue - backFace leftEdge xValue.
  19659.     dz2 _ backFace rightEdge zValue - backFace leftEdge zValue.
  19660.     px _ backFace leftEdge xValue - frontFace leftEdge xValue.
  19661.     pz _ backFace leftEdge zValue - frontFace leftEdge zValue.
  19662.     "Solve the linear equation using cramers rule"
  19663.     det _ (dx1 * dz2) - (dx2 * dz1).
  19664.     det = 0.0 ifTrue:[^errorValue].
  19665.     "det1 _ (dx1 * pz) - (px * dz1)."
  19666.     det2 _ (px * dz2) - (pz * dx2).
  19667.     "det1 _ det1 / det."
  19668.     det2 _ det2 / det.
  19669.     ^frontFace leftEdge xValue + (dx1 * det2) truncated! !
  19670.  
  19671. !B3DScanner methodsFor: 'aet scanning' stamp: 'ar 4/8/1999 03:15'!
  19672. isOnTop: edge at: yValue
  19673.     "Return true if the edge is on top of the current front face"
  19674.     | topFace floatX floatY |
  19675.     topFace _ fillList first.
  19676.     topFace == nil ifTrue:[^true].
  19677.     "Note: It is important to return true if the edge is shared by the top face"
  19678.     (edge leftFace == topFace or:[edge rightFace == topFace]) ifTrue:[^true].
  19679.     floatX _ edge xValue / 4096.0.
  19680.     floatY _ yValue.
  19681.     ^edge zValue < (fillList first zValueAtX: floatX y:  floatY).! !
  19682.  
  19683. !B3DScanner methodsFor: 'aet scanning' stamp: 'ar 4/18/1999 07:23'!
  19684. scanAETAt: yValue
  19685.     "Scan out and draw the active edge table"
  19686.     | leftEdge rightEdge tmp |
  19687.     aet reset.
  19688.     aet atEnd ifTrue:[^nil].
  19689.  
  19690.     "Note the following is debug code that allows restarting this method
  19691.     without getting confused by the face flags. In release mode, having
  19692.     faces in the fillList here would be either an error or due to clipping
  19693.     at the right boundary."
  19694.     fillList do:[:face| face flags: (face flags bitXor: FlagFaceActive)].
  19695.     fillList reset.
  19696.  
  19697.     nextIntersection xValue: 16r3FFFFFFF. "Out of reach"
  19698.     leftEdge _ aet next.
  19699.     "No do the AET scan"
  19700.     [aet atEnd] whileFalse:[
  19701.         "The left edge here is always a top edge. Toggle its fills."
  19702.         self toggleTopFillsOf: leftEdge at: yValue.
  19703.         "After we got a new top face we have to adjust possible intersections."
  19704.         self adjustIntersectionsAt: yValue from: leftEdge. 
  19705.         "Search for the next top edge, which will be the right boundary."
  19706.         rightEdge _ self searchForNewTopEdgeFrom: leftEdge at: yValue.
  19707.         "And fill the stuff"
  19708.         self fillFrom: leftEdge to: rightEdge at: yValue.
  19709.  
  19710.         leftEdge _ rightEdge.
  19711.         "Use a new intersection edge if necessary"
  19712.         leftEdge == nextIntersection ifTrue:[
  19713.             tmp _ nextIntersection.
  19714.             nextIntersection _ lastIntersection.
  19715.             lastIntersection _ tmp].
  19716.         nextIntersection xValue: 16r3FFFFFFF "Must be waaaay off to the right ;-)"
  19717.     ].
  19718.     self toggleBackFillsOf: leftEdge at: yValue validate: false.
  19719.     fillList isEmpty ifFalse:[self error:'FillList not empty'].! !
  19720.  
  19721. !B3DScanner methodsFor: 'aet scanning' stamp: 'ar 4/18/1999 05:59'!
  19722. searchForNewTopEdgeFrom: leftEdge at: yValue
  19723.     "Find the next top edge in the AET. 
  19724.     Note: We have to make sure that intersection edges are returned appropriately."
  19725.     | edge topFace |
  19726.     topFace _ fillList first.
  19727.     topFace == nil ifTrue:[^aet next]. "Next edge must be top"
  19728.     [aet atEnd] whileFalse:[
  19729.         "Check if we have an intersection first."
  19730.         nextIntersection xValue <= aet peek xValue ifTrue:[^nextIntersection].
  19731.         edge _ aet next.
  19732.         "Check if the edge is on top"
  19733.         (self isOnTop: edge at: yValue) ifTrue:[^edge].
  19734.         "If the edge is not on top, toggle the (back) fills of it"
  19735.         self toggleBackFillsOf: edge at: yValue validate: true.
  19736.     ].
  19737.     ^nil! !
  19738.  
  19739. !B3DScanner methodsFor: 'aet scanning' stamp: 'ar 4/7/1999 04:40'!
  19740. toggleBackFillsOf: edge at: yValue validate: aBool
  19741.     "Toggle the faces of the (back) edge"
  19742.     | face |
  19743.     face _ edge leftFace.
  19744.     (face flags anyMask: FlagFaceActive)
  19745.         ifTrue:[    (aBool and:[face == fillList first]) ifTrue:[self error:'Not a back face'].
  19746.                 fillList remove: face]
  19747.         ifFalse:[    fillList addBack: face.
  19748.                 "Check for possible intersections of back and front face"
  19749.                 self checkIntersectionOf: fillList first
  19750.                     with: face at: yValue edge: edge].
  19751.     face flags: (face flags bitXor: FlagFaceActive).
  19752.     face _ edge rightFace.
  19753.     face == nil ifTrue:[^self].
  19754.     (face flags anyMask: FlagFaceActive)
  19755.         ifTrue:[    (aBool and:[face == fillList first]) ifTrue:[self error:'Not a back face'].
  19756.                 fillList remove: face]
  19757.         ifFalse:[    fillList addBack: face.
  19758.                 "Check for possible intersections of back and front face"
  19759.                 self checkIntersectionOf: fillList first
  19760.                     with: face at: yValue edge: edge].
  19761.     face flags: (face flags bitXor: FlagFaceActive).
  19762. ! !
  19763.  
  19764. !B3DScanner methodsFor: 'aet scanning' stamp: 'ar 4/5/1999 23:44'!
  19765. toggleIntersectionEdge: edge
  19766.     "Toggle the faces of the given intersection edge.
  19767.     This is a *very* special case."
  19768.     fillList first == edge leftFace ifFalse:[^self error:'Left face of intersection edge not top face'].
  19769.     fillList remove: edge rightFace.
  19770.     fillList addFront: edge rightFace. ! !
  19771.  
  19772. !B3DScanner methodsFor: 'aet scanning' stamp: 'ar 4/18/1999 06:01'!
  19773. toggleTopFillsOf: edge at: yValue
  19774.     "Toggle the faces of the (new top) edge.
  19775.     We must carefully treat each of the following cases:
  19776.         1) rightFace notNil (e.g., two faces)
  19777.             a) rightFace active ~= leftFace active
  19778.                 => simply swap leftFace and rightFace in the face list
  19779.             b) rightFace active not & leftFace active not
  19780.                 => edge defines new boundary entry; check for minimal dxdz and insert in order
  19781.             c) rightFace active & leftFace active
  19782.                 => edge defines boundary exit; search all faces for minimal z value
  19783.         2) rightFace isNil (e.g., single face)
  19784.             a) leftFace active
  19785.                 => edge defines boundary exit; see 1c)
  19786.             b) leftFace active not
  19787.                 => edge defines boundary entry; simply put it on top.
  19788.     "
  19789.     | leftFace rightFace xorMask noTest |
  19790.     edge == lastIntersection 
  19791.         ifTrue:[^self toggleIntersectionEdge: edge].
  19792.     noTest _ true.
  19793.     leftFace _ edge leftFace.
  19794.     rightFace _ edge rightFace.
  19795.     rightFace == nil ifTrue:[
  19796.         (leftFace flags anyMask: FlagFaceActive)
  19797.             ifTrue:[    leftFace == fillList first | noTest ifFalse:[self error:'Oops'].
  19798.                     fillList remove: leftFace.
  19799.                     fillList searchForNewTopAtX: edge xValue y: yValue]
  19800.             ifFalse:[    fillList addFront: leftFace].
  19801.         leftFace flags: (leftFace flags bitXor: FlagFaceActive).
  19802.         ^self].
  19803.     "rightFace notNil"
  19804.     xorMask _ leftFace flags bitXor: rightFace flags.
  19805.     (xorMask anyMask: FlagFaceActive) ifTrue:[
  19806.         "Simply swap"
  19807.         (leftFace flags anyMask: FlagFaceActive)
  19808.             ifTrue:[    leftFace == fillList first | noTest ifFalse:[self error:'Oops'].
  19809.                     fillList remove: leftFace.
  19810.                     fillList addFront: rightFace]
  19811.             ifFalse:[    rightFace == fillList first | noTest ifFalse:[self error:'Oops'].
  19812.                     fillList remove: rightFace.
  19813.                     fillList addFront: leftFace].
  19814.     ] ifFalse:["rightFace active = leftFace active"
  19815.         (leftFace flags anyMask: FlagFaceActive) ifTrue:[
  19816.             (leftFace == fillList or:[rightFace == fillList first]) | noTest ifFalse:[self error:'Oops'].
  19817.             fillList remove: leftFace.
  19818.             fillList remove: rightFace.
  19819.             fillList searchForNewTopAtX: edge xValue y: yValue.
  19820.         ] ifFalse:[
  19821.             leftFace dzdx <= rightFace dzdx
  19822.                 ifTrue:[    fillList addFront: leftFace.
  19823.                         fillList addBack: rightFace]
  19824.                 ifFalse:[    fillList addFront: rightFace.
  19825.                         fillList addBack: leftFace].
  19826.         ].
  19827.     ].
  19828.     leftFace flags: (leftFace flags bitXor: FlagFaceActive).
  19829.     rightFace flags: (rightFace flags bitXor: FlagFaceActive).
  19830. ! !
  19831.  
  19832. !B3DScanner methodsFor: 'aet updating' stamp: 'ar 4/18/1999 06:02'!
  19833. updateAETAt: yValue
  19834.     "Advance all entries in the AET by one scan line step"
  19835.     | edge count |
  19836.     aet reset.
  19837.     [aet atEnd] whileFalse:[
  19838.         edge _ aet next.
  19839.         count _ edge nLines - 1.
  19840.         count = 0 ifTrue:[
  19841.             "Remove the edge from the AET.
  19842.             If the continuation flag is set, create new (lower) edge(s)."
  19843.             (edge vertex1 windowPosY bitShift: -12) = yValue
  19844.                 ifFalse:[self error:'Edge exceeds range'].
  19845.             aet removeFirst.
  19846.             (edge flags anyMask: FlagContinueLeftEdge)
  19847.                 ifTrue:[self addLowerEdge: edge fromFace: edge leftFace].
  19848.             (edge flags anyMask: FlagContinueRightEdge) 
  19849.                 ifTrue:[self addLowerEdge: edge fromFace: edge rightFace].
  19850.             (edge flags anyMask: FlagEdgeLeftMajor)
  19851.                 ifTrue:[nFaces _ nFaces - 1].
  19852.             (edge flags anyMask: FlagEdgeRightMajor)
  19853.                 ifTrue:[nFaces _ nFaces - 1].
  19854.         ] ifFalse:[
  19855.             "Edge continues. Adjust the number of scan lines remaining
  19856.             and update the incremental values. Make sure that the sorting
  19857.             order of the AET is not getting confused."
  19858.             edge nLines: count. "# of scan lines"
  19859.             edge stepToNextLine. "update incremental values"
  19860.             aet resortFirst. "make sure edge is sorted right"
  19861.         ].
  19862.     ].
  19863. ! !
  19864.  
  19865. !B3DScanner methodsFor: 'span drawing' stamp: 'ar 4/18/1999 05:45'!
  19866. clearSpanBufferAt: yValue
  19867.     spanBuffer primFill: 0.! !
  19868.  
  19869. !B3DScanner methodsFor: 'span drawing' stamp: 'ar 4/18/1999 06:46'!
  19870. drawSpanBufferAt: yValue
  19871.     | leftX rightX |
  19872.     leftX _ aet first xValue bitShift: -12.
  19873.     rightX _ aet last xValue bitShift: -12.
  19874.     bitBlt copyBitsFrom: leftX to: rightX at: yValue.! !
  19875.  
  19876. !B3DScanner methodsFor: 'span drawing' stamp: 'ar 4/18/1999 06:55'!
  19877. fillFrom: leftEdge to: rightEdge at: yValue
  19878.     | face |
  19879.     leftEdge xValue >= rightEdge xValue ifTrue:[^self]. "Nothing to do"
  19880.     face _ fillList first.
  19881.     face == nil ifTrue:[^self].
  19882.     face texture == nil
  19883.         ifTrue:[self rgbFill: face from: leftEdge to: rightEdge at: yValue]
  19884.         ifFalse:[self rgbstwFill: face from: leftEdge to: rightEdge at: yValue]! !
  19885.  
  19886. !B3DScanner methodsFor: 'span drawing' stamp: 'ar 4/18/1999 06:48'!
  19887. rgbFill: face from: leftEdge to: rightEdge at: yValue
  19888.     "Using only RGB (no alpha no textures)"
  19889.     | leftX rightX floatY floatX rValue gValue bValue pv rAttr gAttr bAttr |
  19890.     "Note: We always sample at pixel centers.
  19891.     If the edges do not include this pixel center, do nothing.
  19892.     Otherwise fill from leftX to rightX, including both pixels."
  19893.     leftX _ (leftEdge xValue bitShift: -12) + 1.
  19894.     rightX _ rightEdge xValue bitShift: -12.
  19895.     leftX < 0 ifTrue:[leftX _ 0].
  19896.     rightX >= spanBuffer size ifTrue:[rightX _ spanBuffer size-1].
  19897.     leftX > rightX ifTrue:[^self].
  19898.  
  19899.     B3DScanner doDebug ifTrue:[
  19900.         "Sanity check."
  19901.         (face leftEdge xValue > leftEdge xValue)
  19902.             ifTrue:[
  19903.                 (face rightEdge xValue < rightEdge xValue)
  19904.                     ifTrue:[self error:'Filling outside face']
  19905.                     ifFalse:[self error:'Filling left of face'].
  19906.         ] ifFalse:[(face rightEdge xValue < rightEdge xValue)
  19907.                         ifTrue:[self error:'Filling right of face']].
  19908.     ].
  19909.  
  19910.     (face flags anyMask: FlagFaceInitialized) ifFalse:[
  19911.         face initializePass2.
  19912.         face flags: (face flags bitOr: FlagFaceInitialized)].
  19913.  
  19914.     "@@: Sampling problem!!"
  19915.     floatY _ yValue + 0.5.
  19916.     floatX _ leftX.
  19917.  
  19918.     rAttr _ face attributes.
  19919.     gAttr _ rAttr nextAttr.
  19920.     bAttr _ gAttr nextAttr.
  19921.  
  19922.     rValue _ (face attrValue: rAttr atX: floatX y: floatY).
  19923.     gValue _ (face attrValue: gAttr atX: floatX y: floatY).
  19924.     bValue _ (face attrValue: bAttr atX: floatX y: floatY).
  19925.  
  19926.     [leftX <= rightX] whileTrue:[
  19927.         rValue _ rValue min: 255.0 max: 0.0.
  19928.         gValue _ gValue min: 255.0 max: 0.0.
  19929.         bValue _ bValue min: 255.0 max: 0.0.
  19930.  
  19931.         pv _ (bValue truncated) +
  19932.                 (gValue truncated bitShift: 8) +
  19933.                     (rValue truncated bitShift: 16).
  19934.         spanBuffer at: (leftX _ leftX+1) put: (pv bitOr: 4278190080).
  19935.         rValue _ rValue + rAttr dvdx.
  19936.         gValue _ gValue + gAttr dvdx.
  19937.         bValue _ bValue + bAttr dvdx].
  19938. ! !
  19939.  
  19940. !B3DScanner methodsFor: 'span drawing' stamp: 'ar 4/18/1999 07:22'!
  19941. rgbstwFill: face from: leftEdge to: rightEdge at: yValue
  19942.     "Using only RGB & STW (no alpha)"
  19943.     | leftX rightX floatY floatX rValue gValue bValue pv rAttr gAttr bAttr aAttr wAttr sAttr tAttr wValue sValue tValue texColor |
  19944.     "Note: We always sample at pixel centers.
  19945.     If the edges do not include this pixel center, do nothing.
  19946.     Otherwise fill from leftX to rightX, including both pixels."
  19947.     leftX _ (leftEdge xValue bitShift: -12) + 1.
  19948.     rightX _ rightEdge xValue bitShift: -12.
  19949.     leftX < 0 ifTrue:[leftX _ 0].
  19950.     rightX >= spanBuffer size ifTrue:[rightX _ spanBuffer size-1].
  19951.     leftX > rightX ifTrue:[^self].
  19952.     B3DScanner doDebug ifTrue:[
  19953.         "Sanity check."
  19954.         (face leftEdge xValue > leftEdge xValue)
  19955.             ifTrue:[
  19956.                 (face rightEdge xValue < rightEdge xValue)
  19957.                     ifTrue:[self error:'Filling outside face']
  19958.                     ifFalse:[self error:'Filling left of face'].
  19959.         ] ifFalse:[(face rightEdge xValue < rightEdge xValue)
  19960.                         ifTrue:[self error:'Filling right of face']].
  19961.     ].
  19962.  
  19963.     (face flags anyMask: FlagFaceInitialized) ifFalse:[
  19964.         face initializePass2.
  19965.         face flags: (face flags bitOr: FlagFaceInitialized)].
  19966.  
  19967.     "@@: Sampling problem!!"
  19968.     floatY _ yValue + 0.5.
  19969.     floatX _ leftX.
  19970.  
  19971.     rAttr _ face attributes.
  19972.     gAttr _ rAttr nextAttr.
  19973.     bAttr _ gAttr nextAttr.
  19974.     aAttr _ bAttr nextAttr.
  19975.     wAttr _ aAttr nextAttr.
  19976.     sAttr _ wAttr nextAttr.
  19977.     tAttr _ sAttr nextAttr.
  19978.  
  19979.     rValue _ (face attrValue: rAttr atX: floatX y: floatY).
  19980.     gValue _ (face attrValue: gAttr atX: floatX y: floatY).
  19981.     bValue _ (face attrValue: bAttr atX: floatX y: floatY).
  19982.     wValue _ (face attrValue: wAttr atX: floatX y: floatY).
  19983.     sValue _ (face attrValue: sAttr atX: floatX y: floatY).
  19984.     tValue _ (face attrValue: tAttr atX: floatX y: floatY).
  19985.  
  19986.     [leftX <= rightX] whileTrue:[
  19987.         rValue _ rValue min: 255.0 max: 0.0.
  19988.         gValue _ gValue min: 255.0 max: 0.0.
  19989.         bValue _ bValue min: 255.0 max: 0.0.
  19990.  
  19991.         texColor _ self textureColor: face texture atS: (sValue / wValue) atT: (tValue / wValue).
  19992.  
  19993.         pv _ (bValue * texColor blue) truncated +
  19994.                 ((gValue * texColor green) truncated bitShift: 8) +
  19995.                     ((rValue * texColor red) truncated bitShift: 16).
  19996.         spanBuffer at: (leftX _ leftX+1) put: (pv bitOr: 4278190080).
  19997.         rValue _ rValue + rAttr dvdx.
  19998.         gValue _ gValue + gAttr dvdx.
  19999.         bValue _ bValue + bAttr dvdx.
  20000.         wValue _ wValue + wAttr dvdx.
  20001.         sValue _ sValue + sAttr dvdx.
  20002.         tValue _ tValue + tAttr dvdx].! !
  20003.  
  20004. !B3DScanner methodsFor: 'span drawing' stamp: 'ar 5/28/2000 12:19'!
  20005. textureColor: aTexture atS: sValue atT: tValue
  20006.     "Return the interpolated color of the given texture at s/t"
  20007.     | w h fragS fragT sIndex tIndex peeker tex00 tex01 tex10 tex11 sFrac tFrac mixed |
  20008.     w _ aTexture width.
  20009.     h _ aTexture height.
  20010.     fragS _ w * sValue.
  20011.     fragT _ h * tValue.
  20012.     sIndex _ fragS truncated.
  20013.     tIndex _ fragT truncated.
  20014.     peeker _ BitBlt current bitPeekerFromForm: aTexture.
  20015.     tex00 _ (peeker pixelAt: (sIndex \\ w)@(tIndex \\ h)) asColorOfDepth: aTexture depth.
  20016.     tex01 _ (peeker pixelAt: (sIndex+1 \\ w)@(tIndex \\ h)) asColorOfDepth: aTexture depth.
  20017.     tex10 _ (peeker pixelAt: (sIndex \\ w)@(tIndex+1 \\ h)) asColorOfDepth: aTexture depth.
  20018.     tex11 _ (peeker pixelAt: (sIndex+1 \\ w)@(tIndex+1 \\ h)) asColorOfDepth: aTexture depth.
  20019.     sFrac _ fragS \\ 1.0.
  20020.     tFrac _ fragT \\ 1.0.
  20021.     mixed _ ((1.0 - tFrac) * (((1.0 - sFrac) * tex00 asB3DColor) + (sFrac * tex01 asB3DColor))) +
  20022.             (tFrac * (((1.0 - sFrac) * tex10 asB3DColor) + (sFrac * tex11 asB3DColor))).
  20023.     ^mixed! !
  20024.  
  20025. !B3DScanner methodsFor: 'misc' stamp: 'ar 4/6/1999 03:49'!
  20026. validateAETOrder
  20027.     | last next |
  20028.     aet isEmpty ifTrue:[^self].
  20029.     aet reset.
  20030.     last _ aet next.
  20031.     [aet atEnd] whileFalse:[
  20032.         next _ aet next.
  20033.         last xValue <= next xValue ifFalse:[^self error:'AET is broken'].
  20034.         last _ next].! !
  20035.  
  20036. !B3DScanner methodsFor: 'misc' stamp: 'ar 4/7/1999 05:20'!
  20037. validateEdgesFrom: aCollection
  20038.     "aCollection must contain two entries for each face."
  20039.     | faceNum face faces |
  20040.     faceNum _ 0.
  20041.     aCollection do:[:edge|
  20042.         edge leftFace ifNil:[self error:'Bad edge'] ifNotNil:[faceNum _ faceNum + 1].
  20043.         edge rightFace ifNotNil:[faceNum _ faceNum + 1].
  20044.     ].
  20045.     faceNum \\ 2 = 0 ifTrue:[^self].
  20046.     faces _ Bag new.
  20047.     aCollection do:[:edge|
  20048.         face _ edge leftFace.
  20049.         faces add: face.
  20050.         (aet indexOf: face leftEdge) = 0 ifTrue:[self error:'Left edge not in AET'].
  20051.         (aet indexOf: face rightEdge) = 0 ifTrue:[self error:'Right edge not in AET'].
  20052.         face _ edge rightFace.
  20053.         face == nil ifFalse:[
  20054.             faces add: face.
  20055.             (aet indexOf: face leftEdge) = 0 ifTrue:[self error:'Left edge not in AET'].
  20056.             (aet indexOf: face rightEdge) = 0 ifTrue:[self error:'Right edge not in AET'].
  20057.         ].
  20058.     ].
  20059.     self error:'Something *IS* wrong here'.! !
  20060.  
  20061. !B3DScanner class methodsFor: 'class initialization' stamp: 'ar 4/8/1999 18:30'!
  20062. initialize
  20063.     "B3DScanner initialize"
  20064.     FlagContinueLeftEdge _ 1.
  20065.     FlagContinueRightEdge _ 2.
  20066.     FlagEdgeLeftMajor _ 4.
  20067.     FlagEdgeRightMajor _ 8.
  20068.     FlagFaceActive _ 1.
  20069.     FlagFaceInitialized _ 2.! !
  20070.  
  20071. !B3DScanner class methodsFor: 'instance creation' stamp: 'ar 4/4/1999 04:27'!
  20072. new
  20073.     ^super new initialize! !
  20074.  
  20075. !B3DScanner class methodsFor: 'accessing' stamp: 'ar 4/18/1999 07:24'!
  20076. doDebug
  20077.     ^DebugMode == true! !
  20078.  
  20079. !B3DScanner class methodsFor: 'accessing' stamp: 'ar 4/18/1999 07:25'!
  20080. doDebug: aBool
  20081.     "B3DScanner doDebug: true"
  20082.     "B3DScanner doDebug: false"
  20083.     DebugMode _ aBool.! !
  20084.  
  20085. !B3DScene methodsFor: 'initialize' stamp: 'ti 3/28/2000 13:14'!
  20086. from3DS: aDictionary
  20087.     "Remove the globals from the scene - the remaining objects are
  20088.     name->sceneObject "
  20089.     | globals constants ambient texture funkyNormals r1 |
  20090.     globals _ aDictionary at: #globals.
  20091.     constants _ globals at: #constants ifAbsent: [Dictionary new].
  20092.     aDictionary removeKey: #globals.
  20093.     "Collect the scene objects and assign the names"
  20094.     objects _ OrderedCollection new.
  20095.     aDictionary associationsDo: [:assoc | objects add: ((B3DSceneObject
  20096. from3DS: assoc value)
  20097.                 name: assoc key)].
  20098.     "Fetch the cameras and set a default camera"
  20099.     cameras _ globals at: #cameras.
  20100.     cameras isEmpty
  20101.         ifTrue: [defaultCamera _ B3DCamera new position: 0 @ 0 @ 0]
  20102.         ifFalse: [defaultCamera _ cameras at: cameras keys
  20103. asSortedCollection first].
  20104.     "Fetch the lights"
  20105.     lights _ globals at: #lights.
  20106.     "Add the ambient light if possible.
  20107.     Note: The name $AMBIENT$ is used in the keyframe section of the 3DS
  20108.     file. "
  20109.     ambient _ constants at: 'ambientColor'
  20110.                 ifAbsent: [B3DColor4
  20111.                         r: 0.0
  20112.                         g: 0.0
  20113.                         b: 0.0
  20114.                         a: 0.0].
  20115.     ambient ifNotNil: [lights at: '$AMBIENT$' put: (B3DAmbientLight
  20116. color: ambient)].
  20117.     "Fetch the background color"
  20118.     clearColor _ constants at: 'backgroundColor' ifAbsent: [Color white].
  20119.     "Fetch the materials and replace names in sceneObjects by actual
  20120.     materials "
  20121.     materials _ globals at: #materials.
  20122.     "Compute the per vertex normals"
  20123.     funkyNormals _ self confirm: 'Do you want funky normals instead of
  20124. accurate normals?
  20125. (It will give the model a somewhat strange, but interesting look)'.
  20126.     'Computing vertex normals'
  20127.         displayProgressAt: Sensor cursorPoint
  20128.         from: 0
  20129.         to: objects size
  20130.         during: [:bar | objects
  20131.                 doWithIndex:
  20132.                     [:obj :index |
  20133.                     bar value: index.
  20134.                     obj material ifNotNil: [obj
  20135. material: (materials at: obj material ifAbsent: [])].
  20136.                     funkyNormals
  20137.                         ifTrue: [obj geometry
  20138. computeFunkyVertexNormals]
  20139.                         ifFalse: [obj geometry
  20140. vertexNormals]]].
  20141.     (self confirm: 'Do you want to use a texture with the model?')
  20142.         ifTrue:
  20143.             [Utilities informUser: 'Choose a rectangle with
  20144. interesting stuff'
  20145.                 during:
  20146.                     [r1 _ Rectangle originFromUser: 128
  20147. @ 128.
  20148.                     Sensor waitNoButton].
  20149.             texture _ B3DTexture fromDisplay: r1.
  20150.             texture wrap: true.
  20151.             texture interpolate: false.
  20152.             texture envMode: 0].
  20153.     objects do: [:obj | obj texture ifNotNil: [obj texture: texture]]! !
  20154.  
  20155. !B3DScene methodsFor: 'initialize' stamp: 'ar 2/17/1999 05:09'!
  20156. initialize
  20157.     objects _ OrderedCollection new.
  20158.     cameras _ OrderedCollection new.
  20159.     lights _ OrderedCollection new.
  20160.     materials _OrderedCollection new.
  20161. ! !
  20162.  
  20163. !B3DScene methodsFor: 'initialize' stamp: 'ti 3/28/2000 13:11'!
  20164. withoutQuestionsFrom3DS: aDictionary
  20165.     "Remove the globals from the scene - the remaining objects are
  20166.     name->sceneObject "
  20167.     | globals constants ambient texture funkyNormals |
  20168.     globals _ aDictionary at: #globals.
  20169.     constants _ globals at: #constants ifAbsent: [Dictionary new].
  20170.     aDictionary removeKey: #globals.
  20171.     "Collect the scene objects and assign the names"
  20172.     objects _ OrderedCollection new.
  20173.     aDictionary associationsDo: [:assoc | objects add: ((B3DSceneObject
  20174. from3DS: assoc value)
  20175.                 name: assoc key)].
  20176.     "Fetch the cameras and set a default camera"
  20177.     cameras _ globals at: #cameras.
  20178.     cameras isEmpty
  20179.         ifTrue: [defaultCamera _ B3DCamera new position: 0 @ 0 @ 0]
  20180.         ifFalse: [defaultCamera _ cameras at: cameras keys
  20181. asSortedCollection first].
  20182.     "Fetch the lights"
  20183.     lights _ globals at: #lights.
  20184.     "Add the ambient light if possible.
  20185.     Note: The name $AMBIENT$ is used in the keyframe section of the 3DS
  20186.     file. "
  20187.     ambient _ constants at: 'ambientColor'
  20188.                 ifAbsent: [B3DColor4
  20189.                         r: 0.0
  20190.                         g: 0.0
  20191.                         b: 0.0
  20192.                         a: 0.0].
  20193.     ambient ifNotNil: [lights at: '$AMBIENT$' put: (B3DAmbientLight
  20194. color: ambient)].
  20195.     "Fetch the background color"
  20196.     clearColor _ constants at: 'backgroundColor' ifAbsent: [Color white].
  20197.     "Fetch the materials and replace names in sceneObjects by actual
  20198.     materials "
  20199.     materials _ globals at: #materials.
  20200.     "Compute the per vertex normals"
  20201.     funkyNormals _ false.
  20202.     'Computing vertex normals'
  20203.         displayProgressAt: Sensor cursorPoint
  20204.         from: 0
  20205.         to: objects size
  20206.         during: [:bar | objects
  20207.                 doWithIndex:
  20208.                     [:obj :index |
  20209.                     bar value: index.
  20210.                     obj material ifNotNil: [obj
  20211. material: (materials at: obj material ifAbsent: [])].
  20212.                     funkyNormals
  20213.                         ifTrue: [obj geometry
  20214. computeFunkyVertexNormals]
  20215.                         ifFalse: [obj geometry
  20216. vertexNormals]]].
  20217.     objects do: [:obj | obj texture ifNotNil: [obj texture: texture]]! !
  20218.  
  20219. !B3DScene methodsFor: 'accessing' stamp: 'ar 2/15/1999 01:01'!
  20220. boundingBox
  20221.     |bBox|
  20222.     box ifNotNil:[^box].
  20223.     bBox _ nil.
  20224.     objects do:[:obj|
  20225.         bBox _ bBox ifNil:[obj boundingBox] ifNotNil:[bBox merge: obj boundingBox]
  20226.     ].
  20227.     ^box _ bBox! !
  20228.  
  20229. !B3DScene methodsFor: 'accessing' stamp: 'ti 3/21/2000 11:57'!
  20230. cameras
  20231.     ^cameras! !
  20232.  
  20233. !B3DScene methodsFor: 'accessing' stamp: 'ar 2/17/1999 04:44'!
  20234. clearColor
  20235.     ^clearColor! !
  20236.  
  20237. !B3DScene methodsFor: 'accessing' stamp: 'ar 2/17/1999 04:44'!
  20238. clearColor: aColor
  20239.     clearColor _ aColor! !
  20240.  
  20241. !B3DScene methodsFor: 'accessing' stamp: 'ar 2/15/1999 05:29'!
  20242. defaultCamera
  20243.     ^defaultCamera! !
  20244.  
  20245. !B3DScene methodsFor: 'accessing' stamp: 'ar 2/17/1999 05:08'!
  20246. defaultCamera: aCamera
  20247.     defaultCamera _ aCamera.! !
  20248.  
  20249. !B3DScene methodsFor: 'accessing' stamp: 'jsp 3/1/1999 10:46'!
  20250. lights
  20251.     ^lights! !
  20252.  
  20253. !B3DScene methodsFor: 'accessing' stamp: 'ar 2/17/1999 05:14'!
  20254. objects
  20255.     ^objects! !
  20256.  
  20257. !B3DScene methodsFor: 'accessing' stamp: 'ar 2/17/1999 05:14'!
  20258. objects: aCollection
  20259.     objects _ aCollection! !
  20260.  
  20261. !B3DScene methodsFor: 'displaying' stamp: 'ar 5/28/2000 12:24'!
  20262. render
  20263.     | b3d |
  20264.     b3d _ (B3DRenderEngine defaultForPlatformOn: Display).
  20265.     b3d viewport: (0@0 extent: 600@600).
  20266.     clearColor ifNotNil:[b3d clearViewport: clearColor].
  20267.     b3d clearDepthBuffer.
  20268.     "b3d addLight: (B3DAmbientLight color: Color white)."
  20269.     self renderOn: b3d.
  20270.     b3d finish.
  20271.     b3d destroy.! !
  20272.  
  20273. !B3DScene methodsFor: 'displaying' stamp: 'ar 2/16/1999 05:58'!
  20274. renderOn: aRenderer
  20275.     defaultCamera ifNotNil:[
  20276.         defaultCamera setClippingPlanesFrom: self.
  20277.         defaultCamera aspectRatio: aRenderer viewport aspectRatio.
  20278.         defaultCamera renderOn: aRenderer].
  20279.     lights do:[:light| aRenderer addLight: light].
  20280.     objects do:[:obj| obj renderOn: aRenderer].! !
  20281.  
  20282. !B3DScene class methodsFor: 'instance creation' stamp: 'ar 2/6/1999 23:59'!
  20283. from3DS: aDictionary
  20284.     ^self new from3DS: aDictionary! !
  20285.  
  20286. !B3DScene class methodsFor: 'instance creation' stamp: 'ar 2/17/1999 05:14'!
  20287. new
  20288.     ^super new initialize! !
  20289.  
  20290. !B3DScene class methodsFor: 'instance creation' stamp: 'ti 3/21/2000 15:05'!
  20291. withoutQuestionsFrom3DS: aDictionary
  20292.     ^self new withoutQuestionsFrom3DS: aDictionary! !
  20293.  
  20294. Main comment stating the purpose of this class and relevant relationship to other classes.
  20295.  
  20296. Possible useful expressions for doIt or printIt.
  20297.  
  20298. Structure:
  20299.  instVar1        type -- comment about the purpose of instVar1
  20300.  instVar2        type -- comment about the purpose of instVar2
  20301.  
  20302. Any further useful comments about the general approach of this implementation.!
  20303. !B3DSceneExplorerMorph methodsFor: 'accessing' stamp: 'ti 3/24/2000 17:16'!
  20304. scene
  20305.     ^b3DSceneMorph scene! !
  20306.  
  20307. !B3DSceneExplorerMorph methodsFor: 'accessing' stamp: 'ti 3/24/2000 17:04'!
  20308. scene: aScene
  20309.     b3DSceneMorph scene: aScene.! !
  20310.  
  20311. !B3DSceneExplorerMorph methodsFor: 'actions' stamp: 'ti 3/21/2000 15:08'!
  20312. openThreeDSFile
  20313.     | menu result newFileString myScene |
  20314.     menu := StandardFileMenu oldFileMenu: (FileDirectory default).
  20315.     result := menu startUpWithCaption: 'Select 3DS model file ...'.
  20316.     result ifNotNil: [    
  20317.         newFileString := (result directory pathName),(result directory pathNameDelimiter asString),(result name).
  20318.         myScene := (B3DScene withoutQuestionsFrom3DS: (ThreeDSParser parseFileNamed: newFileString)).
  20319.         myScene := self updateSceneWithDefaults: myScene.
  20320.         self scene: myScene.
  20321.         self updateUpVectorForCamera: self scene defaultCamera.].! !
  20322.  
  20323. !B3DSceneExplorerMorph methodsFor: 'actions' stamp: 'ti 3/21/2000 15:11'!
  20324. selectNewCamera
  20325.     | menu sel |
  20326.     ((self scene cameras isNil) or: [self scene cameras size = 0]) ifTrue: [
  20327.         (SelectionMenu selections: #('OK'))
  20328.             startUpWithCaption: 'No cameras defined!!'.
  20329.         ^self].
  20330.     menu _ SelectionMenu
  20331.         selections: self scene cameras keys asArray.
  20332.     sel := menu startUp.
  20333.     sel ifNotNil: [
  20334.         self scene defaultCamera: (self scene cameras at: sel) copy.
  20335.         self updateUpVectorForCamera: self scene defaultCamera.
  20336.         self changed.]! !
  20337.  
  20338. !B3DSceneExplorerMorph methodsFor: 'actions' stamp: 'ti 3/21/2000 14:28'!
  20339. selectNewCamera: aCameraString
  20340.     aCameraString ifNotNil: [
  20341.         self scene defaultCamera: (self scene cameras at: aCameraString) copy.
  20342.         self updateUpVectorForCamera: self scene defaultCamera.
  20343.         self changed.]! !
  20344.  
  20345. !B3DSceneExplorerMorph methodsFor: 'actions' stamp: 'ti 3/24/2000 17:04'!
  20346. switchRotationStatus
  20347.     b3DSceneMorph switchRotationStatus! !
  20348.  
  20349. !B3DSceneExplorerMorph methodsFor: 'actions' stamp: 'ti 3/24/2000 17:34'!
  20350. updateSceneWithDefaults: myScene
  20351.     | headLight mat |
  20352.     myScene lights at: 'Ambient1' put: (B3DAmbientLight color: (Color gray: 0.2)).
  20353.     headLight := B3DSpotLight new.
  20354.     headLight position: myScene defaultCamera position.
  20355.     headLight target: myScene defaultCamera target.
  20356.     headLight lightColor: (B3DMaterialColor color: (Color gray: 0.7)).
  20357.     headLight attenuation: (B3DLightAttenuation constant: 1.0 linear: 0.0 squared: 0.0).
  20358.     headLight minAngle: 80.
  20359.     headLight maxAngle: 90.
  20360.     myScene lights at: '$HeadLight$' put: headLight copy.
  20361.     mat := B3DMaterial new.
  20362.     mat diffusePart: (Color gray: 0.25).
  20363.     mat ambientPart: (Color gray: 0.01).
  20364.     myScene objects do: [:o|
  20365.         o material: mat].
  20366.     ^myScene! !
  20367.  
  20368. !B3DSceneExplorerMorph methodsFor: 'actions' stamp: 'ti 3/21/2000 12:46'!
  20369. updateUpVectorForCamera: aCamera
  20370.     | oldUp |
  20371.     oldUp := aCamera up.
  20372.     aCamera up:
  20373.         ((aCamera direction cross: oldUp) cross: (aCamera direction))! !
  20374.  
  20375. !B3DSceneExplorerMorph methodsFor: 'change reporting' stamp: 'ti 3/24/2000 17:11'!
  20376. layoutChanged
  20377.     | ctrl |
  20378.     super layoutChanged.
  20379.  
  20380.     b3DSceneMorph ifNil: [^self].
  20381.     b3DSceneMorph extent: (self extent - ((frameWidth * 2)@(frameWidth * 2))).
  20382.     b3DSceneMorph position: (self bounds origin + ((frameWidth)@(frameWidth))).
  20383.  
  20384.     wheels ifNil: [^self].
  20385.     wheels isEmpty ifTrue: [^self].
  20386.  
  20387.     ctrl := wheels at: #fov ifAbsent: [nil].
  20388.     ctrl ifNotNil: [
  20389.         ctrl position:
  20390.             self bounds corner -
  20391.                 ctrl extent - 
  20392.                 (frameWidth@((frameWidth - ctrl extent y) / 2) rounded)].
  20393.  
  20394.     ctrl := wheels at: #dolly ifAbsent: [nil].
  20395.     ctrl ifNotNil: [
  20396.         ctrl position:
  20397.             self bounds corner -
  20398.                 ctrl extent - 
  20399.                 ((((frameWidth - ctrl extent x) / 2) rounded)@frameWidth)].
  20400.  
  20401.     ctrl := wheels at: #rotX ifAbsent: [nil].
  20402.     ctrl ifNotNil: [
  20403.         ctrl position:
  20404.             (self bounds origin x + (((frameWidth - ctrl extent x) / 2) rounded))@(self bounds corner y - ctrl extent y - frameWidth)].
  20405.  
  20406.     ctrl := wheels at: #rotY ifAbsent: [nil].
  20407.     ctrl ifNotNil: [
  20408.         ctrl position:
  20409.             (self bounds origin x + frameWidth)@(self bounds corner y - ctrl extent y - (((frameWidth - ctrl extent y) / 2) rounded))].
  20410.  
  20411.     ctrl := wheels at: #rotZ ifAbsent: [nil].
  20412.     ctrl ifNotNil: [
  20413.         ctrl position:
  20414.             self bounds origin +
  20415.             ((((frameWidth - ctrl extent x) / 2) rounded)@frameWidth)].! !
  20416.  
  20417. !B3DSceneExplorerMorph methodsFor: 'drawing' stamp: 'ti 3/24/2000 17:27'!
  20418. drawOn: aCanvas
  20419.     super drawOn: aCanvas.
  20420.     aCanvas fillRectangle: (self bounds insetBy: frameWidth) color: Color black.! !
  20421.  
  20422. !B3DSceneExplorerMorph methodsFor: 'event handling' stamp: 'ti 3/24/2000 17:13'!
  20423. handlesMouseDown: evt
  20424.     ^evt yellowButtonPressed
  20425. ! !
  20426.  
  20427. !B3DSceneExplorerMorph methodsFor: 'event handling' stamp: 'ti 3/24/2000 17:14'!
  20428. mouseDown: evt
  20429.     evt yellowButtonPressed ifTrue: [
  20430.         self yellowButtonMenu.
  20431.         ^super mouseDown: evt].! !
  20432.  
  20433. !B3DSceneExplorerMorph methodsFor: 'initialization' stamp: 'ti 3/24/2000 17:23'!
  20434. initialize
  20435.     | ctrl |
  20436.     super initialize.
  20437.     self extent: 300@300.
  20438.     self borderRaised.
  20439.     color := Color gray: 0.8.
  20440.     frameWidth := 25.
  20441.  
  20442.     b3DSceneMorph := AdvancedB3DSceneMorph new.
  20443.     self addMorphFront: b3DSceneMorph.
  20444.     
  20445.     wheels := Dictionary new.
  20446.     ctrl := WheelMorph new.
  20447.     ctrl target: b3DSceneMorph.
  20448.     ctrl actionSelector: #addFovAngle:.
  20449.     ctrl factor: -0.07.
  20450.     ctrl setBalloonText: 'FOV'.
  20451.     self addMorphFront: ctrl.
  20452.     wheels at: #fov put: ctrl.
  20453.  
  20454.     ctrl := WheelMorph new.
  20455.     ctrl target: b3DSceneMorph.
  20456.     ctrl actionSelector: #addDolly:.
  20457.     ctrl factor: 0.005.
  20458.     ctrl beVertical.
  20459.     ctrl setBalloonText: 'Dolly'.
  20460.     self addMorphFront: ctrl.
  20461.     wheels at: #dolly put: ctrl.
  20462.  
  20463.     ctrl := WheelMorph new.
  20464.     ctrl target: b3DSceneMorph.
  20465.     ctrl actionSelector: #rotateZ:.
  20466.     ctrl beVertical.
  20467.     ctrl setBalloonText: 'z Axis'.
  20468.     self addMorphFront: ctrl.
  20469.     wheels at: #rotZ put: ctrl.
  20470.  
  20471.     ctrl := WheelMorph new.
  20472.     ctrl target: b3DSceneMorph.
  20473.     ctrl actionSelector: #rotateY:.
  20474.     ctrl setBalloonText: 'y Axis'.
  20475.     self addMorphFront: ctrl.
  20476.     wheels at: #rotY put: ctrl.
  20477.  
  20478.     ctrl := WheelMorph new.
  20479.     ctrl target: b3DSceneMorph.
  20480.     ctrl actionSelector: #rotateX:.
  20481.     ctrl beVertical.
  20482.     ctrl setBalloonText: 'x Axis'.
  20483.     self addMorphFront: ctrl.
  20484.     wheels at: #rotX put: ctrl.! !
  20485.  
  20486. !B3DSceneExplorerMorph methodsFor: 'menus' stamp: 'ti 3/22/2000 19:05'!
  20487. addCustomMenuItems: aCustomMenu
  20488.  
  20489.     (aCustomMenu isKindOf: MenuMorph)
  20490.         ifTrue: [aCustomMenu addUpdating: #rotationString action: #switchRotationStatus]
  20491.         ifFalse: [aCustomMenu add: 'swich rotation status' action: #switchRotationStatus].
  20492.     aCustomMenu add: 'open 3DS file' action: #openThreeDSFile.
  20493.     aCustomMenu add: 'select new camera' action: #selectNewCamera.! !
  20494.  
  20495. !B3DSceneExplorerMorph methodsFor: 'menus' stamp: 'ti 3/22/2000 18:51'!
  20496. addCustomMenuItems: aCustomMenu hand: aHandMorph
  20497.  
  20498.     super addCustomMenuItems: aCustomMenu hand: aHandMorph.
  20499.     aCustomMenu addLine.
  20500.     self addCustomMenuItems: aCustomMenu.! !
  20501.  
  20502. !B3DSceneExplorerMorph methodsFor: 'menus' stamp: 'ti 3/24/2000 17:04'!
  20503. rotationString
  20504.     ^b3DSceneMorph isRotating
  20505.         ifTrue: ['stop rotating']
  20506.         ifFalse: ['start rotating']! !
  20507.  
  20508. !B3DSceneExplorerMorph methodsFor: 'menus' stamp: 'ti 3/22/2000 18:57'!
  20509. yellowButtonMenu
  20510.     | menu sel |
  20511.     menu _ CustomMenu new.
  20512.     menu title: self class name.
  20513.     self addCustomMenuItems: menu.
  20514.     sel := menu startUp.
  20515.     sel ifNotNil: [self perform: sel]! !
  20516.  
  20517. !B3DSceneExplorerMorph methodsFor: 'visual properties' stamp: 'ti 3/21/2000 14:45'!
  20518. defaultColor
  20519.     ^Color gray! !
  20520.  
  20521. !B3DSceneMorph methodsFor: 'drawing' stamp: 'ar 5/25/2000 17:57'!
  20522. debugDraw
  20523.     self fullDrawOn: (Display getCanvas).
  20524.     Display forceToScreen: bounds.! !
  20525.  
  20526. !B3DSceneMorph methodsFor: 'drawing' stamp: 'ar 2/17/1999 05:05'!
  20527. drawOn: aCanvas
  20528.     aCanvas asBalloonCanvas render: self.
  20529. ! !
  20530.  
  20531. !B3DSceneMorph methodsFor: 'drawing' stamp: 'ar 2/17/1999 05:34'!
  20532. renderOn: aRenderer
  20533.     aRenderer viewport: (self bounds insetBy: 1@1).
  20534.     aRenderer clearDepthBuffer.
  20535.     aRenderer loadIdentity.
  20536.     scene renderOn: aRenderer.! !
  20537.  
  20538. !B3DSceneMorph methodsFor: 'initialize' stamp: 'ar 2/17/1999 05:27'!
  20539. createDefaultScene
  20540.     | sceneObj camera |
  20541.     sceneObj _ B3DSceneObject named: 'Sample Cube'.
  20542.     sceneObj geometry: (B3DBox from: (-0.7@-0.7@-0.7) to: (0.7@0.7@0.7)).
  20543.     camera _ B3DCamera new.
  20544.     camera position: 0@0@-1.5.
  20545.     self extent: 100@100.
  20546.     scene _ B3DScene new.
  20547.     scene defaultCamera: camera.
  20548.     scene objects add: sceneObj.! !
  20549.  
  20550. !B3DSceneMorph methodsFor: 'initialize' stamp: 'ar 2/17/1999 05:24'!
  20551. initialize
  20552.     super initialize.
  20553.     self createDefaultScene.! !
  20554.  
  20555. !B3DSceneMorph methodsFor: 'accessing' stamp: 'ar 2/17/1999 05:34'!
  20556. scene
  20557.     ^scene! !
  20558.  
  20559. !B3DSceneMorph methodsFor: 'accessing' stamp: 'ar 2/17/1999 05:34'!
  20560. scene: aScene
  20561.     scene _ aScene! !
  20562.  
  20563. !B3DSceneMorph methodsFor: 'stepping' stamp: 'ar 2/17/1999 05:31'!
  20564. step
  20565.     scene defaultCamera rotateBy: 15.
  20566.     self changed.! !
  20567.  
  20568. !B3DSceneMorph methodsFor: 'stepping' stamp: 'ar 2/17/1999 05:31'!
  20569. stepTime
  20570.     ^1! !
  20571.  
  20572. !B3DSceneMorph methodsFor: 'stepping' stamp: 'ar 2/17/1999 05:30'!
  20573. wantsSteps
  20574.     ^true! !
  20575.  
  20576. !B3DSceneObject methodsFor: 'initialize' stamp: 'ar 2/16/1999 03:09'!
  20577. from3DS: aDictionary
  20578.     aDictionary isEmpty ifTrue:[^nil].
  20579.     geometry _ B3DSTriangleMesh from3DS: aDictionary.
  20580.     material _ (aDictionary at: #triList) last.! !
  20581.  
  20582. !B3DSceneObject methodsFor: 'accessing' stamp: 'ar 2/14/1999 22:37'!
  20583. boundingBox
  20584.     | bBox |
  20585.     bBox _ geometry ifNotNil:[geometry boundingBox].
  20586.     children ifNil:[^bBox].
  20587.     children do:[:obj|
  20588.         bBox _ bBox ifNil:[obj boundingBox] ifNotNil:[bBox merge: obj boundingBox]
  20589.     ].
  20590.     ^bBox! !
  20591.  
  20592. !B3DSceneObject methodsFor: 'accessing' stamp: 'ar 2/7/1999 19:29'!
  20593. geometry
  20594.     ^geometry! !
  20595.  
  20596. !B3DSceneObject methodsFor: 'accessing' stamp: 'ar 2/7/1999 19:30'!
  20597. geometry: aGeometry
  20598.     geometry _ aGeometry.! !
  20599.  
  20600. !B3DSceneObject methodsFor: 'accessing' stamp: 'ar 2/7/1999 19:30'!
  20601. material
  20602.     ^material! !
  20603.  
  20604. !B3DSceneObject methodsFor: 'accessing' stamp: 'ar 2/16/1999 03:10'!
  20605. material: aMaterial
  20606.     material _ aMaterial.
  20607.     material class == Association ifTrue:[
  20608.         texture _ material key.
  20609.         material _ material value.
  20610.     ].! !
  20611.  
  20612. !B3DSceneObject methodsFor: 'accessing' stamp: 'ar 2/7/1999 19:30'!
  20613. matrix
  20614.     ^matrix! !
  20615.  
  20616. !B3DSceneObject methodsFor: 'accessing' stamp: 'ar 2/7/1999 19:30'!
  20617. matrix: aMatrix
  20618.     matrix _ aMatrix! !
  20619.  
  20620. !B3DSceneObject methodsFor: 'accessing' stamp: 'ar 2/7/1999 20:06'!
  20621. name
  20622.     ^name! !
  20623.  
  20624. !B3DSceneObject methodsFor: 'accessing' stamp: 'ar 2/7/1999 20:06'!
  20625. name: aString
  20626.     name _ aString.! !
  20627.  
  20628. !B3DSceneObject methodsFor: 'accessing' stamp: 'ar 2/16/1999 03:01'!
  20629. texture
  20630.     ^texture! !
  20631.  
  20632. !B3DSceneObject methodsFor: 'accessing' stamp: 'ar 2/16/1999 03:01'!
  20633. texture: aTexture
  20634.     texture _ aTexture! !
  20635.  
  20636. !B3DSceneObject methodsFor: 'displaying' stamp: 'ar 2/16/1999 03:13'!
  20637. renderOn: aRenderer
  20638.     material ifNotNil:[
  20639.         aRenderer pushMaterial.
  20640.         aRenderer material: material].
  20641.     texture ifNotNil:[
  20642.         aRenderer pushTexture.
  20643.         aRenderer texture: texture].
  20644.     matrix ifNotNil:[
  20645.         aRenderer pushMatrix.
  20646.         aRenderer transformBy: matrix].
  20647.     geometry ifNotNil:[geometry renderOn: aRenderer].
  20648.     children ifNotNil:[children do:[:child| child renderOn: aRenderer]].
  20649.     matrix ifNotNil:[aRenderer popMatrix].
  20650.     texture ifNotNil:[aRenderer popTexture].
  20651.     material ifNotNil:[aRenderer popMaterial].! !
  20652.  
  20653. !B3DSceneObject methodsFor: 'printing' stamp: 'ar 2/8/1999 01:15'!
  20654. printOn: aStream
  20655.     super printOn: aStream.
  20656.     aStream
  20657.         nextPut:$(;
  20658.         print: self name;
  20659.         nextPut: $).! !
  20660.  
  20661. !B3DSceneObject class methodsFor: 'instance creation' stamp: 'ar 2/8/1999 01:06'!
  20662. from3DS: aDictionary
  20663.     ^self new from3DS: aDictionary! !
  20664.  
  20665. !B3DSceneObject class methodsFor: 'instance creation' stamp: 'ar 2/7/1999 20:06'!
  20666. named: aString
  20667.     ^self new name: aString! !
  20668.  
  20669. !B3DShaderPlugin methodsFor: 'primitives' stamp: 'ar 2/17/1999 19:40'!
  20670. b3dShadeVertexBuffer
  20671.     "Primitive. Shade all the vertices in the vertex buffer using the given array of primitive light sources. Return true on success."
  20672.     | lightArray vtxCount vtxArray lightCount |
  20673.     self export: true.
  20674.     self inline: false.
  20675.     self var: #vtxArray declareC:'float *vtxArray'.
  20676.     vbFlags _ interpreterProxy stackIntegerValue: 0.
  20677.     primMaterial _ self stackMaterialValue: 1.
  20678.     lightArray _ self stackLightArrayValue: 2.
  20679.     vtxCount _ interpreterProxy stackIntegerValue: 3.
  20680.     vtxArray _ self stackPrimitiveVertexArray: 4 ofSize: vtxCount.
  20681.     (vtxArray = nil or:[primMaterial = nil or:[interpreterProxy failed]])
  20682.         ifTrue:[^interpreterProxy primitiveFail].
  20683.     "Setup"
  20684.     litVertex _ vtxArray.
  20685.     lightCount _ interpreterProxy slotSizeOf: lightArray.
  20686.     "Go over all vertices"
  20687.     1 to: vtxCount do:[:i|
  20688.         "Load the primitive vertex"
  20689.         self loadPrimitiveVertex.
  20690.         "Load initial color (e.g., emissive part of vertex and/or material)"
  20691.         (vbFlags anyMask: VBTrackEmission) ifTrue:[
  20692.             "Load color from vertex"
  20693.             vtxOutColor at: 0 put: (vtxInColor at: 0) + (primMaterial at: EmissionRed).
  20694.             vtxOutColor at: 1 put: (vtxInColor at: 1) + (primMaterial at: EmissionGreen).
  20695.             vtxOutColor at: 2 put: (vtxInColor at: 2) + (primMaterial at: EmissionBlue).
  20696.             vtxOutColor at: 3 put: (vtxInColor at: 3) + (primMaterial at: EmissionAlpha).
  20697.         ] ifFalse:[
  20698.             vtxOutColor at: 0 put: (primMaterial at: EmissionRed).
  20699.             vtxOutColor at: 1 put: (primMaterial at: EmissionGreen).
  20700.             vtxOutColor at: 2 put: (primMaterial at: EmissionBlue).
  20701.             vtxOutColor at: 3 put: (primMaterial at: EmissionAlpha).
  20702.         ].
  20703.         "For each enabled light source"
  20704.         0 to: lightCount-1 do:[:j|
  20705.             "Fetch the light source"
  20706.             primLight _ self fetchLightSource: j ofObject: lightArray.
  20707.             "Setup values"
  20708.             self loadPrimitiveLightSource.
  20709.             "Compute the color from the light source"
  20710.             self shadeVertex.
  20711.         ].
  20712.         "Store the computed color back"
  20713.         self storePrimitiveVertex.
  20714.         "And step on to the next vertex"
  20715.         litVertex _ litVertex + PrimVertexSize.
  20716.     ].
  20717.     "Clean up stack"
  20718.     interpreterProxy pop: 6. "Pop args+rcvr"
  20719.     interpreterProxy pushBool: true.! !
  20720.  
  20721. !B3DShaderPlugin methodsFor: 'primitives' stamp: 'ar 2/17/1999 04:32'!
  20722. b3dShaderVersion
  20723.     "Return the current shader version."
  20724.     self export: true.
  20725.     self inline: false.
  20726.     interpreterProxy pop: 1.
  20727.     interpreterProxy pushInteger: 1.    "Version 1"! !
  20728.  
  20729. !B3DShaderPlugin methodsFor: 'shading' stamp: 'ar 2/17/1999 19:40'!
  20730. addPart: lightPart from: materialPart trackFlag: vbTrackFlag scale: scale
  20731.     "Add the given light part to the output color, scaled by the given scale factor.
  20732.     If the given flag is set in vbFlags then load the part from the primitive vertex"
  20733.     | rPart gPart bPart aPart |
  20734.     self var: #lightPart declareC:'float *lightPart'.
  20735.     self var: #materialPart declareC:'float *materialPart'.
  20736.     self var: #scale declareC:'double scale'.
  20737.     self var: #rPart declareC:'double rPart'.
  20738.     self var: #gPart declareC:'double gPart'.
  20739.     self var: #bPart declareC:'double bPart'.
  20740.     self var: #aPart declareC:'double aPart'.
  20741.     self inline: true.
  20742.     (vbFlags anyMask: vbTrackFlag) ifTrue:[
  20743.         rPart _ (vtxInColor at: 0) * (lightPart at: 0) * scale.
  20744.         gPart _ (vtxInColor at: 1) * (lightPart at: 1) * scale.
  20745.         bPart _ (vtxInColor at: 2) * (lightPart at: 2) * scale.
  20746.         aPart _ (vtxInColor at: 3) * (lightPart at: 3) * scale.
  20747.     ] ifFalse:[
  20748.         "Note: This should be pre-computed."
  20749.         rPart _ (materialPart at: 0) * (lightPart at: 0) * scale.
  20750.         gPart _ (materialPart at: 1) * (lightPart at: 1) * scale.
  20751.         bPart _ (materialPart at: 2) * (lightPart at: 2) * scale.
  20752.         aPart _ (materialPart at: 3) * (lightPart at: 3) * scale.
  20753.     ].
  20754.     vtxOutColor at: 0 put: (vtxOutColor at: 0) + rPart.
  20755.     vtxOutColor at: 1 put: (vtxOutColor at: 1) + gPart.
  20756.     vtxOutColor at: 2 put: (vtxOutColor at: 2) + bPart.
  20757.     vtxOutColor at: 3 put: (vtxOutColor at: 3) + aPart.! !
  20758.  
  20759. !B3DShaderPlugin methodsFor: 'shading' stamp: 'ar 2/17/1999 19:39'!
  20760. computeAttenuation
  20761.     "Compute the attenuation for the current light and vertex"
  20762.     lightScale _ 1.0.
  20763.     (lightFlags anyMask: FlagAttenuated) ifTrue:[
  20764.         lightScale _ 1.0 / ((primLight at: PrimLightAttenuationConstant) + 
  20765.             (l2vDistance * ((primLight at: PrimLightAttenuationLinear) + 
  20766.                 (l2vDistance * (primLight at: PrimLightAttenuationSquared)))))].
  20767. ! !
  20768.  
  20769. !B3DShaderPlugin methodsFor: 'shading' stamp: 'ar 4/17/1999 22:31'!
  20770. computeDirection
  20771.     "Compute the direction for the current light and vertex"
  20772.     | scale |
  20773.     self inline: true.
  20774.     self var: #scale declareC:'double scale'.
  20775.     (lightFlags anyMask: FlagPositional) ifTrue:[
  20776.         "Must compute the direction for this vertex"
  20777.         l2vDirection at: 0 put: (litVertex at: PrimVtxPositionX) - (primLight at: PrimLightPositionX).
  20778.         l2vDirection at: 1 put: (litVertex at: PrimVtxPositionY) - (primLight at: PrimLightPositionY).
  20779.         l2vDirection at: 2 put: (litVertex at: PrimVtxPositionZ) - (primLight at: PrimLightPositionZ).
  20780.         "l2vDistance _ self dotProductOf: l2vDirection with: l2vDirection."
  20781.         l2vDistance _ ((l2vDirection at: 0) * (l2vDirection at: 0)) +
  20782.                         ((l2vDirection at: 1) * (l2vDirection at: 1)) +
  20783.                             ((l2vDirection at: 2) * (l2vDirection at: 2)).
  20784.         (l2vDistance = 0.0 or:[l2vDistance = 1.0]) 
  20785.             ifFalse:[    l2vDistance _ l2vDistance sqrt.
  20786.                     scale _ -1.0/l2vDistance].
  20787.         l2vDirection at: 0 put: (l2vDirection at: 0) * scale.
  20788.         l2vDirection at: 1 put: (l2vDirection at: 1) * scale.
  20789.         l2vDirection at: 2 put: (l2vDirection at: 2) * scale.
  20790.     ] ifFalse:[
  20791.         (lightFlags anyMask: FlagDirectional) ifTrue:[
  20792.             l2vDirection at: 0 put: (primLight at: PrimLightDirectionX).
  20793.             l2vDirection at: 1 put: (primLight at: PrimLightDirectionY).
  20794.             l2vDirection at: 2 put: (primLight at: PrimLightDirectionZ).
  20795.         ].
  20796.     ].
  20797. ! !
  20798.  
  20799. !B3DShaderPlugin methodsFor: 'shading' stamp: 'ar 4/17/1999 22:39'!
  20800. computeSpecularDirection
  20801.     "Computes
  20802.         l2vSpecDir _ l2vSpecDir - vtx position safelyNormalized.
  20803.     "
  20804.     | scale |
  20805.     self var: #scale declareC:'double scale'.
  20806.     scale _ self inverseLengthOfFloat: litVertex + PrimVtxPosition.
  20807.     l2vSpecDir at: 0 put: (l2vSpecDir at: 0) - ((litVertex at: PrimVtxPositionX) * scale).
  20808.     l2vSpecDir at: 1 put: (l2vSpecDir at: 1) - ((litVertex at: PrimVtxPositionY) * scale).
  20809.     l2vSpecDir at: 2 put: (l2vSpecDir at: 2) - ((litVertex at: PrimVtxPositionZ) * scale).
  20810. ! !
  20811.  
  20812. !B3DShaderPlugin methodsFor: 'shading' stamp: 'ar 4/17/1999 22:39'!
  20813. computeSpotFactor
  20814.     "Compute the spot factor for a spot light"
  20815.     | cosAngle minCos deltaCos |
  20816.     self returnTypeC:'double'.
  20817.     self var: #cosAngle declareC:'double cosAngle'.
  20818.     self var: #minCos declareC:'double minCos'.
  20819.     self var: #deltaCos declareC:'double deltaCos'.
  20820.     "Compute cos angle between direction of the spot light and direction to vertex"
  20821.     cosAngle _ self dotProductOfFloat: primLight + PrimLightDirection withDouble: l2vDirection.
  20822.     cosAngle _ 0.0 - cosAngle.
  20823.     minCos _ primLight at: SpotLightMinCos.
  20824.     cosAngle < minCos ifTrue:[^0.0].
  20825.     deltaCos _ primLight at: SpotLightDeltaCos.
  20826.     deltaCos <= 0.00001 ifTrue:[
  20827.         "No delta -- a sharp boundary between on and off.
  20828.         Since off has already been determined above, we are on"
  20829.         ^1.0].
  20830.     "Scale the angle to 0/1 range"
  20831.     cosAngle _ (cosAngle - minCos) / deltaCos.
  20832.     ^cosAngle raisedTo: (primLight at: SpotLightExponent)
  20833. ! !
  20834.  
  20835. !B3DShaderPlugin methodsFor: 'shading' stamp: 'ar 4/17/1999 22:39'!
  20836. dotProductOfFloat: v1 withDouble: v2
  20837.     self var: #v1 declareC:'float * v1'.
  20838.     self var: #v2 declareC:'double *v2'.
  20839.     self returnTypeC:'double'.
  20840.     ^((v1 at: 0) * (v2 at: 0)) +
  20841.         ((v1 at: 1) * (v2 at: 1)) +
  20842.             ((v1 at: 2) * (v2 at: 2)).
  20843. ! !
  20844.  
  20845. !B3DShaderPlugin methodsFor: 'shading' stamp: 'ar 4/17/1999 22:38'!
  20846. inverseLengthOfDouble: aVector
  20847.     | scale |
  20848.     self returnTypeC:'double'.
  20849.     self var: #aVector declareC:'double * aVector'.
  20850.     self var: #scale declareC:'double scale'.
  20851.     "scale _ self dotProductOf: aVector with: aVector."
  20852.     scale _ ((aVector at: 0) * (aVector at: 0)) +
  20853.                 ((aVector at: 1) * (aVector at: 1)) +
  20854.                     ((aVector at: 2) * (aVector at: 2)).
  20855.     (scale = 0.0 or:[scale = 1.0]) ifTrue:[^scale].
  20856.     ^1.0 / scale sqrt! !
  20857.  
  20858. !B3DShaderPlugin methodsFor: 'shading' stamp: 'ar 4/17/1999 22:38'!
  20859. inverseLengthOfFloat: aVector
  20860.     | scale |
  20861.     self returnTypeC:'double'.
  20862.     self var: #aVector declareC:'float * aVector'.
  20863.     self var: #scale declareC:'double scale'.
  20864.     "scale _ self dotProductOf: aVector with: aVector."
  20865.     scale _ ((aVector at: 0) * (aVector at: 0)) +
  20866.                 ((aVector at: 1) * (aVector at: 1)) +
  20867.                     ((aVector at: 2) * (aVector at: 2)).
  20868.     (scale = 0.0 or:[scale = 1.0]) ifTrue:[^scale].
  20869.     ^1.0 / scale sqrt! !
  20870.  
  20871. !B3DShaderPlugin methodsFor: 'shading' stamp: 'ar 4/17/1999 22:40'!
  20872. shadeVertex
  20873.     | cosAngle specularFactor |
  20874.     self var: #cosAngle declareC:'double cosAngle'.
  20875.     self var: #specularFactor declareC:'double specularFactor'.
  20876.     self computeDirection.
  20877.     self computeAttenuation.
  20878.  
  20879.     (lightFlags anyMask: FlagHasSpot) ifTrue:[
  20880.         lightScale _ lightScale * self computeSpotFactor.
  20881.     ].
  20882.  
  20883.     "Compute ambient and diffuse part only if lightScale is non-zero."
  20884.     (lightScale > 0.001) ifTrue:[
  20885.         "Compute the ambient part"
  20886.         (lightFlags anyMask: FlagAmbientPart) ifTrue:[
  20887.             self addPart: (primLight + AmbientPart) 
  20888.                 from: primMaterial + AmbientPart 
  20889.                 trackFlag: VBTrackAmbient 
  20890.                 scale: lightScale.
  20891.         ].
  20892.  
  20893.         "Compute the diffuse part"
  20894.         (lightFlags anyMask: FlagDiffusePart) ifTrue:[
  20895.             "Compute angle from light->vertex to vertex normal"
  20896.             cosAngle _ self dotProductOfFloat: (litVertex + PrimVtxNormal) withDouble: l2vDirection.
  20897.             "For one-sided lighting negate cosAngle if necessary"
  20898.             ((vbFlags bitAnd: VBTwoSidedLighting) = 0 and:[cosAngle < 0.0])
  20899.                 ifTrue:[cosAngle _ 0.0 - cosAngle].
  20900.             "For two-sided lighting check if cosAngle > 0.0 meaning that it is a front face"
  20901.             cosAngle > 0.0 ifTrue:[
  20902.                 self addPart: primLight + DiffusePart 
  20903.                     from: primMaterial + DiffusePart 
  20904.                     trackFlag: VBTrackDiffuse 
  20905.                     scale: lightScale * cosAngle.
  20906.             ].
  20907.         ].
  20908.     ]. "lightScale > 0.001"
  20909.  
  20910.     "Compute the specular part"
  20911.     ((lightFlags anyMask: FlagSpecularPart) and:[
  20912.         (primMaterial at: MaterialShininess) > 0.0]) ifTrue:[
  20913.         "Compute specular part"
  20914.         l2vSpecDir at: 0 put: (l2vDirection at: 0).
  20915.         l2vSpecDir at: 1 put: (l2vDirection at: 1).
  20916.         l2vSpecDir at: 2 put: (l2vDirection at: 2).
  20917.         (vbFlags anyMask: VBUseLocalViewer) 
  20918.             ifTrue:[self computeSpecularDirection]
  20919.             ifFalse:[l2vSpecDir at: 2 put: (l2vSpecDir at: 2) - 1.0].
  20920.         cosAngle _ self dotProductOfFloat: (litVertex + PrimVtxNormal) withDouble: l2vSpecDir.
  20921.         cosAngle > 0.0 ifTrue:[
  20922.             "Normalize the angle"
  20923.             cosAngle _ cosAngle * (self inverseLengthOfDouble: l2vSpecDir).
  20924.             "cosAngle should be somewhere between 0 and 1.
  20925.             If not, then the vertex normal was not normalized"
  20926.             cosAngle > 1.0 ifTrue:[
  20927.                 specularFactor _ cosAngle raisedTo: (primMaterial at: MaterialShininess).
  20928.             ] ifFalse:[
  20929.                 cosAngle = 0.0 
  20930.                     ifTrue:[specularFactor _ 1.0]
  20931.                     ifFalse:[specularFactor _ cosAngle raisedTo: (primMaterial at: MaterialShininess)].
  20932.             ].
  20933.             self addPart: primLight + SpecularPart 
  20934.                 from: primMaterial + SpecularPart 
  20935.                 trackFlag: VBTrackSpecular 
  20936.                 scale: specularFactor.
  20937.         ].
  20938.     ].! !
  20939.  
  20940. !B3DShaderPlugin methodsFor: 'primitive support' stamp: 'ar 2/15/1999 22:33'!
  20941. fetchLightSource: index ofObject: anArray
  20942.     "Fetch the primitive light source from the given array.
  20943.     Note: No checks are done within here - that happened in stackLightArrayValue:"
  20944.     | lightOop |
  20945.     self inline: true.
  20946.     self returnTypeC:'void*'.
  20947.     lightOop _ interpreterProxy fetchPointer: index ofObject: anArray.
  20948.     ^interpreterProxy firstIndexableField: lightOop! !
  20949.  
  20950. !B3DShaderPlugin methodsFor: 'primitive support' stamp: 'ar 2/15/1999 22:29'!
  20951. stackLightArrayValue: stackIndex
  20952.     "Load an Array of B3DPrimitiveLights from the given stack index"
  20953.     | oop array arraySize |
  20954.     self inline: false.
  20955.     array _ interpreterProxy stackObjectValue: stackIndex.
  20956.     interpreterProxy failed ifTrue:[^nil].
  20957.     (interpreterProxy fetchClassOf: array) = interpreterProxy classArray
  20958.         ifFalse:[^interpreterProxy primitiveFail].
  20959.     arraySize _ interpreterProxy slotSizeOf: array.
  20960.     0 to: arraySize-1 do:[:i|
  20961.         oop _ interpreterProxy fetchPointer: i ofObject: array.
  20962.         (interpreterProxy isIntegerObject: oop)
  20963.             ifTrue:[^interpreterProxy primitiveFail].
  20964.         ((interpreterProxy isWords: oop) and:[(interpreterProxy slotSizeOf: oop) = PrimLightSize])
  20965.             ifFalse:[^interpreterProxy primitiveFail].
  20966.     ].
  20967.     ^array! !
  20968.  
  20969. !B3DShaderPlugin methodsFor: 'primitive support' stamp: 'ar 2/15/1999 19:22'!
  20970. stackMaterialValue: stackIndex
  20971.     "Load a B3DMaterial from the given stack index"
  20972.     | oop |
  20973.     self inline: false.
  20974.     self returnTypeC:'void *'.
  20975.     oop _ interpreterProxy stackObjectValue: stackIndex.
  20976.     interpreterProxy failed ifTrue:[^nil].
  20977.     ((interpreterProxy isWords: oop) and:[(interpreterProxy slotSizeOf: oop) = MaterialSize])
  20978.         ifTrue:[^interpreterProxy firstIndexableField: oop].
  20979.     ^nil! !
  20980.  
  20981. !B3DShaderPlugin methodsFor: 'other' stamp: 'ar 2/17/1999 19:35'!
  20982. loadPrimitiveLightSource
  20983.     self inline: true.
  20984.     lightFlags _ (self cCoerce: primLight to: 'int*') at: PrimLightFlags.! !
  20985.  
  20986. !B3DShaderPlugin methodsFor: 'other' stamp: 'ar 2/17/1999 19:40'!
  20987. loadPrimitiveVertex
  20988.     "Load the necessary values from the current primitive vertex"
  20989.     | rgba |
  20990.     self inline: true.
  20991.     rgba _ (self cCoerce: litVertex to:'int*') at: PrimVtxColor32.
  20992.     vtxInColor at: 2 put: (rgba bitAnd: 255) * (1.0 / 255.0).
  20993.     rgba _ rgba >> 8.
  20994.     vtxInColor at: 1 put: (rgba bitAnd: 255) * (1.0 / 255.0).
  20995.     rgba _ rgba >> 8.
  20996.     vtxInColor at: 0 put: (rgba bitAnd: 255) * (1.0 / 255.0).
  20997.     rgba _ rgba >> 8.
  20998.     vtxInColor at: 3 put: (rgba bitAnd: 255) * (1.0 / 255.0).
  20999. ! !
  21000.  
  21001. !B3DShaderPlugin methodsFor: 'other' stamp: 'ar 2/17/1999 19:41'!
  21002. storePrimitiveVertex
  21003.     "Store the computed output color back into the current primitive vertex.
  21004.     Clamp the r,g,b,a part to be in the range 0-255."
  21005.     | r g b a |
  21006.     self inline: true.
  21007.     r _ ((vtxOutColor at: 0) * 255) asInteger.
  21008.     r _ (r min: 255) max: 0.
  21009.     g _ ((vtxOutColor at: 1) * 255) asInteger.
  21010.     g _ (g min: 255) max: 0.
  21011.     b _ ((vtxOutColor at: 2) * 255) asInteger.
  21012.     b _ (b min: 255) max: 0.
  21013.     a _ ((vtxOutColor at: 3) * 255) asInteger.
  21014.     a _ (a min: 255) max: 0.
  21015.     "The following is equal to b + (g << 8) + (r << 16) + (a << 24)"
  21016.     (self cCoerce: litVertex to:'int*') 
  21017.         at: PrimVtxColor32 put: b + (g + (r + (a << 8) << 8) << 8). 
  21018. ! !
  21019.  
  21020. !B3DShaderPlugin class methodsFor: 'translation' stamp: 'ar 5/15/2000 23:13'!
  21021. declareCVarsIn: cg
  21022.     cg var: #litVertex type: #'float*'.
  21023.     cg var: #primLight type: #'float*'.
  21024.     cg var: #primMaterial type: #'float*'.
  21025.     cg var: #l2vDirection declareC: 'double l2vDirection[3]'.
  21026.     cg var: #l2vSpecDir declareC: 'double l2vSpecDir[3]'.
  21027.     cg var: #vtxInColor declareC: 'double vtxInColor[4]'.
  21028.     cg var: #vtxOutColor declareC: 'double vtxOutColor[4]'.
  21029.     cg var: #l2vDistance type: #'double'.
  21030.     cg var: #lightScale type: #'double'! !
  21031.  
  21032. !B3DSimpleMesh methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:54'!
  21033. boundingBox
  21034.     ^bBox ifNil:[bBox _ self computeBoundingBox]! !
  21035.  
  21036. !B3DSimpleMesh methodsFor: 'accessing' stamp: 'ar 9/14/1999 22:53'!
  21037. colorOfVertex: vtx
  21038.     ^vtx color! !
  21039.  
  21040. !B3DSimpleMesh methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:55'!
  21041. computeBoundingBox
  21042.     | min max |
  21043.     min _ max _ nil.
  21044.     self vertexPositionsDo:[:vtx|
  21045.         min ifNil:[min _ vtx] ifNotNil:[min _ min min: vtx].
  21046.         max ifNil:[max _ vtx] ifNotNil:[max _ max max: vtx].
  21047.     ].
  21048.     ^Rectangle origin: min corner: max! !
  21049.  
  21050. !B3DSimpleMesh methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:54'!
  21051. faces
  21052.     ^self! !
  21053.  
  21054. !B3DSimpleMesh methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:54'!
  21055. faces: aCollection
  21056.     ^self shouldNotImplement! !
  21057.  
  21058. !B3DSimpleMesh methodsFor: 'accessing' stamp: 'ar 9/14/1999 22:53'!
  21059. normalOfVertex: vtx
  21060.     ^vtx normal! !
  21061.  
  21062. !B3DSimpleMesh methodsFor: 'accessing' stamp: 'ar 9/14/1999 22:54'!
  21063. texCoordOfVertex: vtx
  21064.     ^vtx texCoord! !
  21065.  
  21066. !B3DSimpleMesh methodsFor: 'testing' stamp: 'ar 9/14/1999 22:53'!
  21067. hasTextureCoords
  21068.     1 to: self size do:[:i|
  21069.         (self at: i) hasTextureCoords ifFalse:[^false]].
  21070.     ^true! !
  21071.  
  21072. !B3DSimpleMesh methodsFor: 'testing' stamp: 'ar 9/14/1999 22:52'!
  21073. hasVertexColors
  21074.     1 to: self size do:[:i|
  21075.         (self at: i) hasVertexColors ifFalse:[^false]].
  21076.     ^true! !
  21077.  
  21078. !B3DSimpleMesh methodsFor: 'enumerating' stamp: 'ar 9/17/1999 12:38'!
  21079. do: aBlock
  21080.     1 to: self size do:[:i| aBlock value: (self at: i)]! !
  21081.  
  21082. !B3DSimpleMesh methodsFor: 'enumerating' stamp: 'ar 9/14/1999 22:02'!
  21083. trianglesDo: aBlock
  21084.     1 to: self size do:[:i|
  21085.         (self at: i) trianglesDo: aBlock.
  21086.     ].! !
  21087.  
  21088. !B3DSimpleMesh methodsFor: 'enumerating' stamp: 'ar 9/14/1999 21:56'!
  21089. vertexPositionsDo: aBlock
  21090.     1 to: self size do:[:i|
  21091.         (self at: i) vertexPositionsDo: aBlock.
  21092.     ]! !
  21093.  
  21094. !B3DSimpleMesh methodsFor: 'converting' stamp: 'ar 9/14/1999 22:26'!
  21095. asIndexedMesh
  21096.     "Convert the receiver into (the more compact) indexed representation"
  21097.     ^self asIndexedTriangleMesh! !
  21098.  
  21099. !B3DSimpleMesh methodsFor: 'converting' stamp: 'ar 9/14/1999 22:17'!
  21100. asIndexedTriangleMesh
  21101.     "Convert the receiver into (the more compact) indexed triangle representation"
  21102.     | map faces face vtx nrm tex col mesh |
  21103.     map _ Dictionary new: (self size * 4). "Need some space for the vertices"
  21104.     faces _ WriteStream on: (B3DIndexedTriangleArray new: self size).
  21105.     self trianglesDo:[:tri|
  21106.         tri assureVertexNormals.
  21107.         face _ B3DIndexedTriangle
  21108.                     with: (map at: tri first ifAbsentPut:[map size + 1])
  21109.                     with: (map at: tri second ifAbsentPut:[map size + 1])
  21110.                     with: (map at: tri third ifAbsentPut:[map size + 1]).
  21111.         faces nextPut: face].
  21112.     faces _ faces contents.
  21113.     vtx _ B3DVector3Array new: map size.
  21114.     nrm _ B3DVector3Array new: map size.
  21115.     self hasTextureCoords ifTrue:[tex _ B3DTexture2Array new: map size].
  21116.     self hasVertexColors ifTrue:[col _ B3DColor4Array new: map size].
  21117.     map keysAndValuesDo:[:vertex :idx|
  21118.         vtx at: idx put: vertex position.
  21119.         nrm at: idx put: vertex normal.
  21120.         tex == nil ifFalse:[tex at: idx put: vertex texCoord].
  21121.         col == nil ifFalse:[col at: idx put: vertex color].
  21122.     ].
  21123.     mesh _ B3DIndexedTriangleMesh new.
  21124.     mesh faces: faces.
  21125.     mesh vertices: vtx.
  21126.     mesh texCoords: tex.
  21127.     mesh vertexColors: col.
  21128.     mesh vertexNormals: nrm.
  21129.     ^mesh! !
  21130.  
  21131. !B3DSimpleMesh methodsFor: 'converting' stamp: 'ar 9/14/1999 22:05'!
  21132. asSimpleMesh
  21133.     ^self! !
  21134.  
  21135. !B3DSimpleMesh methodsFor: 'converting' stamp: 'ar 9/17/1999 12:31'!
  21136. transformedBy: aMatrix
  21137.     "Return a copy of the receiver with its vertices transformed by the given matrix"
  21138.     | newFaces|
  21139.     newFaces _ Array new: self size.
  21140.     1 to: self size do:[:i| newFaces at: i put: ((self at: i) transformedBy: aMatrix)].
  21141.     ^self class withAll: newFaces! !
  21142.  
  21143. !B3DSimpleMesh methodsFor: 'rendering' stamp: 'ar 11/7/1999 18:15'!
  21144. renderOn: aRenderer
  21145.     | box bounds |
  21146.     box _ nil.
  21147.     1 to: self size do:[:i|
  21148.         bounds _ (self at: i) renderOn: aRenderer.
  21149.         box == nil ifTrue:[box _ bounds] ifFalse:[box _ box quickMerge: bounds].
  21150.     ].
  21151.     ^box! !
  21152.  
  21153. !B3DSimpleMesh methodsFor: 'private' stamp: 'ar 9/14/1999 23:01'!
  21154. withAll: aCollection
  21155.     1 to: self size do:[:i|
  21156.         self at: i put: (aCollection at: i).
  21157.     ].! !
  21158.  
  21159. !B3DSimpleMesh class methodsFor: 'instance creation' stamp: 'ar 9/14/1999 23:00'!
  21160. withAll: aCollection
  21161.     ^(self new: aCollection size) withAll: aCollection! !
  21162.  
  21163. !B3DSimpleMeshFace methodsFor: 'accessing' stamp: 'ar 9/14/1999 22:50'!
  21164. first
  21165.     ^self at: 1! !
  21166.  
  21167. !B3DSimpleMeshFace methodsFor: 'accessing' stamp: 'ar 9/14/1999 22:50'!
  21168. fourth
  21169.     ^self at: 4! !
  21170.  
  21171. !B3DSimpleMeshFace methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:51'!
  21172. normal
  21173.     ^normal ifNil:[normal _ self computeFaceNormal].! !
  21174.  
  21175. !B3DSimpleMeshFace methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:53'!
  21176. normal: aB3DVector3
  21177.     normal _ aB3DVector3! !
  21178.  
  21179. !B3DSimpleMeshFace methodsFor: 'accessing' stamp: 'ar 9/14/1999 22:50'!
  21180. second
  21181.     ^self at: 2! !
  21182.  
  21183. !B3DSimpleMeshFace methodsFor: 'accessing' stamp: 'ar 9/14/1999 22:50'!
  21184. third
  21185.     ^self at: 3! !
  21186.  
  21187. !B3DSimpleMeshFace methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:53'!
  21188. vertices
  21189.     ^self! !
  21190.  
  21191. !B3DSimpleMeshFace methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:53'!
  21192. vertices: aCollection
  21193.     ^self shouldNotImplement.! !
  21194.  
  21195. !B3DSimpleMeshFace methodsFor: 'testing' stamp: 'ar 9/14/1999 23:05'!
  21196. hasTextureCoords
  21197.     1 to: self size do:[:i|
  21198.         (self at: i) hasTextureCoords ifFalse:[^false]].
  21199.     ^true! !
  21200.  
  21201. !B3DSimpleMeshFace methodsFor: 'testing' stamp: 'ar 9/14/1999 23:05'!
  21202. hasVertexColors
  21203.     1 to: self size do:[:i|
  21204.         (self at: i) hasVertexColors ifFalse:[^false]].
  21205.     ^true! !
  21206.  
  21207. !B3DSimpleMeshFace methodsFor: 'enumerating' stamp: 'ar 9/17/1999 12:38'!
  21208. do: aBlock
  21209.     1 to: self size do:[:i| aBlock value: (self at: i)]! !
  21210.  
  21211. !B3DSimpleMeshFace methodsFor: 'enumerating' stamp: 'ar 9/14/1999 22:01'!
  21212. trianglesDo: aBlock
  21213.     "Evaluate aBlock with triangular faces"
  21214.     | face |
  21215.     self size = 3
  21216.         ifTrue:[^aBlock value: self].
  21217.     3 to: self size do:[:i|
  21218.         face _ self class with: (self at: 1) with: (self at: i-1) with: (self at: i).
  21219.         aBlock value: face].! !
  21220.  
  21221. !B3DSimpleMeshFace methodsFor: 'enumerating' stamp: 'ar 9/14/1999 21:56'!
  21222. vertexPositionsDo: aBlock
  21223.     1 to: self size do:[:i|
  21224.         (self at: i) vertexPositionsDo: aBlock.
  21225.     ]! !
  21226.  
  21227. !B3DSimpleMeshFace methodsFor: 'rendering' stamp: 'ar 11/7/1999 18:14'!
  21228. renderOn: aRenderer
  21229.     ^aRenderer drawPolygonAfter:[
  21230.         aRenderer normal: self normal.
  21231.         1 to: self size do:[:i| (self at: i) renderOn: aRenderer].
  21232.     ].! !
  21233.  
  21234. !B3DSimpleMeshFace methodsFor: 'private' stamp: 'ar 9/14/1999 23:09'!
  21235. computeFaceNormal
  21236.     | d1 d2 nrml |
  21237.     self size < 3 ifTrue:[^B3DVector3 zero].
  21238.     d1 _ (self at: 1) position - (self at: 2) position.
  21239.     d2 _ (self at: 3) position - (self at: 2) position.
  21240.     d1 safelyNormalize.
  21241.     d2 safelyNormalize.
  21242.     nrml _ d1 cross: d2.
  21243.     ^nrml safelyNormalize! !
  21244.  
  21245. !B3DSimpleMeshFace methodsFor: 'private' stamp: 'ar 9/14/1999 22:04'!
  21246. with: v1 with: v2 with: v3
  21247.     self at: 1 put: v1;
  21248.         at: 2 put: v2;
  21249.         at: 3 put: v3! !
  21250.  
  21251. !B3DSimpleMeshFace methodsFor: 'private' stamp: 'ar 9/14/1999 22:04'!
  21252. with: v1 with: v2 with: v3 with: v4
  21253.     self at: 1 put: v1;
  21254.         at: 2 put: v2;
  21255.         at: 3 put: v3;
  21256.         at: 4 put: v4! !
  21257.  
  21258. !B3DSimpleMeshFace methodsFor: 'private' stamp: 'ar 9/14/1999 22:05'!
  21259. withAll: aCollection
  21260.     1 to: self size do:[:i|
  21261.         self at: i put: (aCollection at: i).
  21262.     ].! !
  21263.  
  21264. !B3DSimpleMeshFace methodsFor: 'misc' stamp: 'ar 9/14/1999 22:51'!
  21265. assureVertexNormals
  21266.     | vtx |
  21267.     1 to: self size do:[:i|
  21268.         vtx _ self at: i.
  21269.         vtx normal == nil ifTrue:[
  21270.             vtx _ vtx copy.
  21271.             vtx normal: self normal.
  21272.             self at: i put: vtx]].! !
  21273.  
  21274. !B3DSimpleMeshFace methodsFor: 'converting' stamp: 'ar 9/17/1999 12:31'!
  21275. transformedBy: aMatrix
  21276.     "Return a copy of the receiver with its vertices transformed by the given matrix"
  21277.     | newVtx |
  21278.     newVtx _ Array new: self size.
  21279.     1 to: self size do:[:i| newVtx at: i put: ((self at: i) transformedBy: aMatrix)].
  21280.     ^self class withAll: newVtx! !
  21281.  
  21282. !B3DSimpleMeshFace class methodsFor: 'instance creation' stamp: 'ar 9/14/1999 22:03'!
  21283. with: v0 with: v1 with: v2
  21284.     ^(self new: 3) with: v0 with: v1 with: v2! !
  21285.  
  21286. !B3DSimpleMeshFace class methodsFor: 'instance creation' stamp: 'ar 9/14/1999 22:03'!
  21287. with: v0 with: v1 with: v2 with: v3
  21288.     ^(self new: 4) with: v0 with: v1 with: v2 with: v3! !
  21289.  
  21290. !B3DSimpleMeshFace class methodsFor: 'instance creation' stamp: 'ar 9/14/1999 22:03'!
  21291. withAll: aCollection
  21292.     ^(self new: aCollection size) withAll: aCollection! !
  21293.  
  21294. !B3DSimpleMeshVertex methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:46'!
  21295. color
  21296.     ^color! !
  21297.  
  21298. !B3DSimpleMeshVertex methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:46'!
  21299. color: aB3DColor4
  21300.     color _ aB3DColor4! !
  21301.  
  21302. !B3DSimpleMeshVertex methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:45'!
  21303. normal
  21304.     ^normal! !
  21305.  
  21306. !B3DSimpleMeshVertex methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:46'!
  21307. normal: aB3DVector3
  21308.     normal _ aB3DVector3! !
  21309.  
  21310. !B3DSimpleMeshVertex methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:45'!
  21311. position
  21312.     ^position! !
  21313.  
  21314. !B3DSimpleMeshVertex methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:45'!
  21315. position: aB3DVector3
  21316.     position _ aB3DVector3! !
  21317.  
  21318. !B3DSimpleMeshVertex methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:46'!
  21319. texCoord
  21320.     ^texCoord! !
  21321.  
  21322. !B3DSimpleMeshVertex methodsFor: 'accessing' stamp: 'ar 9/14/1999 21:46'!
  21323. texCoord: aB3DVector2
  21324.     texCoord _ aB3DVector2! !
  21325.  
  21326. !B3DSimpleMeshVertex methodsFor: 'testing' stamp: 'ar 9/14/1999 23:06'!
  21327. hasTextureCoords
  21328.     ^texCoord notNil! !
  21329.  
  21330. !B3DSimpleMeshVertex methodsFor: 'testing' stamp: 'ar 9/14/1999 23:06'!
  21331. hasVertexColors
  21332.     ^color notNil! !
  21333.  
  21334. !B3DSimpleMeshVertex methodsFor: 'comparing' stamp: 'ar 9/14/1999 21:48'!
  21335. = aVertex
  21336.     ^self class == aVertex class
  21337.         and:[self position = aVertex position
  21338.             and:[self normal = aVertex normal
  21339.                 and:[self color = aVertex color
  21340.                     and:[self texCoord = aVertex texCoord]]]]! !
  21341.  
  21342. !B3DSimpleMeshVertex methodsFor: 'comparing' stamp: 'ar 9/14/1999 21:49'!
  21343. hash
  21344.     "Hash is re-implemented because #= is re-implemented"
  21345.     ^(position hash bitXor: texCoord hash) bitXor:
  21346.         (normal hash bitXor: color hash)! !
  21347.  
  21348. !B3DSimpleMeshVertex methodsFor: 'enumerating' stamp: 'ar 9/14/1999 21:56'!
  21349. vertexPositionsDo: aBlock
  21350.     position vertexPositionsDo: aBlock.! !
  21351.  
  21352. !B3DSimpleMeshVertex methodsFor: 'rendering' stamp: 'ar 9/14/1999 21:59'!
  21353. renderOn: aRenderer
  21354.     color == nil ifFalse:[aRenderer color: color].
  21355.     texCoord == nil ifFalse:[aRenderer texCoord: texCoord].
  21356.     normal == nil ifFalse:[aRenderer normal: normal].
  21357.     aRenderer vertex: position.! !
  21358.  
  21359. !B3DSimpleMeshVertex methodsFor: 'printing' stamp: 'ar 9/16/1999 22:48'!
  21360. printOn: aStream
  21361.     aStream nextPutAll:'['; print: position; nextPutAll:']'.! !
  21362.  
  21363. !B3DSimpleMeshVertex methodsFor: 'converting' stamp: 'ar 9/17/1999 13:30'!
  21364. transformedBy: aMatrix
  21365.     "Return a copy of the receiver with its vertices transformed by the given matrix"
  21366.     | transformer copy |
  21367.     transformer _ B3DVertexTransformer new.
  21368.     transformer loadIdentity.
  21369.     transformer transformBy: aMatrix.
  21370.     copy _ self copy.
  21371.     copy position: (transformer transformPosition: position).
  21372.     normal == nil
  21373.         ifFalse:[copy normal: (transformer transformDirection: normal) safelyNormalize].
  21374.     ^copy! !
  21375.  
  21376. !B3DSimulRasterizer methodsFor: 'initialize' stamp: 'ar 5/26/2000 15:45'!
  21377. clipRect: aRectangle
  21378.     super clipRect: aRectangle.
  21379.     scanner bitBlt clipRect: aRectangle.! !
  21380.  
  21381. !B3DSimulRasterizer methodsFor: 'initialize' stamp: 'ar 4/18/1999 04:35'!
  21382. flush
  21383.     self mainLoop.! !
  21384.  
  21385. !B3DSimulRasterizer methodsFor: 'initialize' stamp: 'ar 4/18/1999 04:36'!
  21386. initialize
  21387.     super initialize.
  21388.     scanner _ B3DScanner new.! !
  21389.  
  21390. !B3DSimulRasterizer methodsFor: 'initialize' stamp: 'ar 4/18/1999 04:36'!
  21391. reset
  21392.     super reset.
  21393.     scanner _ B3DScanner new.! !
  21394.  
  21395. !B3DSimulRasterizer methodsFor: 'initialize' stamp: 'ar 5/28/2000 12:18'!
  21396. target: destForm
  21397.     | bb span sourceForm |
  21398.     super target: destForm.
  21399.     span _ Bitmap new: 2048.
  21400.     sourceForm _ Form extent: span size@1 depth: 32 bits: span.
  21401.     bb _ BitBlt current toForm: destForm.
  21402.     bb sourceForm: sourceForm.
  21403.     bb isFXBlt ifTrue:[
  21404.         bb colorMap: (sourceForm colormapIfNeededFor: destForm).
  21405.         bb combinationRule: 34 "Form paint". "Later we'll change this to 34 for alpha blending"
  21406.     ] ifFalse:[
  21407.         bb colorMap: (sourceForm colormapIfNeededForDepth: destForm depth).
  21408.         bb combinationRule: 34 "Form paint". "Later we'll change this to 34 for alpha blending"
  21409.     ].
  21410.     bb destX: 0; destY: 0; sourceX: 0; sourceY: 0; width: 1; height: 1.
  21411.     scanner spanBuffer: span.
  21412.     scanner bitBlt: bb.! !
  21413.  
  21414. !B3DSimulRasterizer methodsFor: 'testing' stamp: 'ar 4/18/1999 04:36'!
  21415. needsClip
  21416.     ^true! !
  21417.  
  21418. !B3DSimulRasterizer methodsFor: 'processing' stamp: 'ar 4/18/1999 04:48'!
  21419. loadVerticesFrom: vb
  21420.     | out vtxArray |
  21421.     vtxArray _ vb vertexArray.
  21422.     out _ Array new: vb vertexCount.
  21423.     1 to: vb vertexCount do:[:i|
  21424.         out at: i put: (vtxArray at: i).
  21425.     ].
  21426.     ^out! !
  21427.  
  21428. !B3DSimulRasterizer methodsFor: 'processing' stamp: 'ar 4/18/1999 05:31'!
  21429. mainLoop
  21430.     scanner mainLoop.
  21431.     scanner resetObjects.! !
  21432.  
  21433. !B3DSimulRasterizer methodsFor: 'processing' stamp: 'ar 4/18/1999 07:34'!
  21434. processIndexedQuads: vb
  21435.     | vtxArray out idx1 idxArray idx2 idx3 face obj idx4 |
  21436.     vtxArray _ self loadVerticesFrom: vb.
  21437.     idxArray _ vb indexArray.
  21438.     out _ WriteStream on: (B3DIndexedTriangleArray new: vb indexCount // 3 * 2).
  21439.     1 to: vb indexCount by: 4 do:[:i|
  21440.         idx1 _ idxArray at: i.
  21441.         idx2 _ idxArray at: i+1.
  21442.         idx3 _ idxArray at: i+2.
  21443.         idx4 _ idxArray at: i+3.
  21444.         idx1 = 0 ifFalse:[
  21445.             face _ B3DIndexedTriangle with: idx1 with: idx2 with: idx3.
  21446.             out nextPut: face.
  21447.             face _ B3DIndexedTriangle with: idx3 with: idx4 with: idx1.
  21448.             out nextPut: face].
  21449.     ].
  21450.     obj _ B3DPrimitiveObject new.
  21451.     obj faces: out contents.
  21452.     obj vertices: vtxArray.
  21453.     obj texture: texture.
  21454.     obj mapVertices: viewport.
  21455.     obj setupVertexOrder.
  21456.     obj sortInitialFaces.
  21457.     scanner addObject: obj.! !
  21458.  
  21459. !B3DSimulRasterizer methodsFor: 'processing' stamp: 'ar 4/18/1999 06:55'!
  21460. processIndexedTriangles: vb
  21461.     | vtxArray out idx1 idxArray idx2 idx3 face obj |
  21462.     vtxArray _ self loadVerticesFrom: vb.
  21463.     idxArray _ vb indexArray.
  21464.     out _ WriteStream on: (B3DIndexedTriangleArray new: vb indexCount // 3).
  21465.     1 to: vb indexCount by: 3 do:[:i|
  21466.         idx1 _ idxArray at: i.
  21467.         idx2 _ idxArray at: i+1.
  21468.         idx3 _ idxArray at: i+2.
  21469.         idx1 = 0 ifFalse:[
  21470.             face _ B3DIndexedTriangle with: idx1 with: idx2 with: idx3.
  21471.             out nextPut: face].
  21472.     ].
  21473.     obj _ B3DPrimitiveObject new.
  21474.     obj faces: out contents.
  21475.     obj vertices: vtxArray.
  21476.     obj texture: texture.
  21477.     obj mapVertices: viewport.
  21478.     obj setupVertexOrder.
  21479.     obj sortInitialFaces.
  21480.     scanner addObject: obj.! !
  21481.  
  21482. !B3DSimulRasterizer methodsFor: 'processing' stamp: 'ar 4/18/1999 07:56'!
  21483. processPolygon: vb
  21484.     | vtxArray out face obj |
  21485.     vtxArray _ self loadVerticesFrom: vb.
  21486.     out _ WriteStream on: (B3DIndexedTriangleArray new: vtxArray size - 2).
  21487.     3 to: vb vertexCount do:[:i|
  21488.         face _ B3DIndexedTriangle with: 1 with: i-1 with: i.
  21489.         out nextPut: face.
  21490.     ].
  21491.     obj _ B3DPrimitiveObject new.
  21492.     obj faces: out contents.
  21493.     obj vertices: vtxArray.
  21494.     obj texture: texture.
  21495.     obj mapVertices: viewport.
  21496.     obj setupVertexOrder.
  21497.     obj sortInitialFaces.
  21498.     scanner addObject: obj.! !
  21499.  
  21500. !B3DSimulRasterizer class methodsFor: 'testing'!
  21501. isAvailable
  21502.     ^true "Always"! !
  21503.  
  21504. !B3DSpotLight methodsFor: 'initialize' stamp: 'ar 2/7/1999 18:44'!
  21505. from3DS: aDictionary
  21506.     "Initialize the receiver from a 3DS point light"
  21507.     | spotValues hotSpot fallOff |
  21508.     super from3DS: aDictionary.
  21509.     spotValues _ aDictionary at: #spot.
  21510.     target _ spotValues at: #target.
  21511.     hotSpot _ spotValues at: #hotspotAngle.
  21512.     self minAngle: hotSpot.
  21513.     fallOff _ spotValues at: #falloffAngle.
  21514.     self maxAngle: hotSpot + fallOff.! !
  21515.  
  21516. !B3DSpotLight methodsFor: 'accessing' stamp: 'ar 2/7/1999 18:18'!
  21517. direction
  21518.     ^direction ifNil:[direction _ (target - position) safelyNormalize].! !
  21519.  
  21520. !B3DSpotLight methodsFor: 'accessing' stamp: 'ar 2/8/1999 01:40'!
  21521. direction: aVector
  21522.     direction _ aVector! !
  21523.  
  21524. !B3DSpotLight methodsFor: 'accessing' stamp: 'ar 2/7/1999 18:47'!
  21525. hotSpotDeltaCosine
  21526.     ^deltaCos! !
  21527.  
  21528. !B3DSpotLight methodsFor: 'accessing' stamp: 'ar 2/7/1999 18:45'!
  21529. hotSpotMaxCosine
  21530.     ^maxCos! !
  21531.  
  21532. !B3DSpotLight methodsFor: 'accessing' stamp: 'ar 2/7/1999 18:45'!
  21533. hotSpotMinCosine
  21534.     ^minCos! !
  21535.  
  21536. !B3DSpotLight methodsFor: 'accessing' stamp: 'ar 2/7/1999 18:46'!
  21537. maxAngle
  21538.     ^maxCos arcCos radiansToDegrees! !
  21539.  
  21540. !B3DSpotLight methodsFor: 'accessing' stamp: 'ar 2/7/1999 20:25'!
  21541. maxAngle: angle
  21542.     minCos _ angle degreesToRadians cos.
  21543.     maxCos ifNotNil:[deltaCos _ maxCos - minCos].! !
  21544.  
  21545. !B3DSpotLight methodsFor: 'accessing' stamp: 'ar 2/7/1999 18:46'!
  21546. minAngle
  21547.     ^minCos arcCos radiansToDegrees! !
  21548.  
  21549. !B3DSpotLight methodsFor: 'accessing' stamp: 'ar 2/7/1999 20:25'!
  21550. minAngle: angle
  21551.     maxCos _ angle degreesToRadians cos.
  21552.     minCos ifNotNil:[deltaCos _ maxCos - minCos].! !
  21553.  
  21554. !B3DSpotLight methodsFor: 'accessing' stamp: 'ar 2/7/1999 20:16'!
  21555. target
  21556.     ^target! !
  21557.  
  21558. !B3DSpotLight methodsFor: 'accessing' stamp: 'ar 2/7/1999 20:16'!
  21559. target: aVector
  21560.     target _ aVector! !
  21561.  
  21562. !B3DSpotLight methodsFor: 'testing' stamp: 'ar 2/15/1999 02:18'!
  21563. hasSpot
  21564.     ^true! !
  21565.  
  21566. !B3DSpotLight methodsFor: 'converting' stamp: 'ar 2/15/1999 22:01'!
  21567. asPrimitiveLight
  21568.     "Convert the receiver into a B3DPrimitiveLight"
  21569.     | primLight |
  21570.     primLight _ super asPrimitiveLight.
  21571.     primLight flags: (primLight flags bitOr: FlagHasSpot).
  21572.     primLight spotMinCos: minCos.
  21573.     primLight spotMaxCos: maxCos.
  21574.     primLight spotDeltaCos: deltaCos.
  21575.     primLight spotExponent: self spotExponent.
  21576.     primLight direction: (target - position) safelyNormalize.
  21577.     ^primLight! !
  21578.  
  21579. !B3DSpotLight methodsFor: 'converting' stamp: 'ar 2/8/1999 01:39'!
  21580. transformedBy: aTransformer
  21581.     ^(super transformedBy: aTransformer) 
  21582.         target: (aTransformer transformPosition: target);
  21583.         direction: nil! !
  21584.  
  21585. I represent a simple 2D texture.
  21586.  
  21587. Instance variables:
  21588.     wrap        <Boolean>    If true, wrap the texture - otherwise clamp it.
  21589.     interpolate    <Boolean>    If true, interpolate the pixels of the texture.
  21590.     envMode    <Integer>    How we combine colors with the texture.
  21591.         Possible values:
  21592.             0 - OpenGL style modulate texture
  21593.             1 - OpenGL style decal texture!
  21594. !B3DTexture methodsFor: 'accessing' stamp: 'ar 6/9/2000 19:16'!
  21595. contentsOfArea: aRect
  21596.      "Return a new form which derives from the portion of the original form delineated by aRect."
  21597.     ^self contentsOfArea: aRect 
  21598.         into: ((self class extent: aRect extent depth: depth)
  21599.                 wrap: self wrap;
  21600.                 envMode: self envMode;
  21601.                 interpolate: self interpolate;
  21602.                 yourself)! !
  21603.  
  21604. !B3DTexture methodsFor: 'accessing' stamp: 'ar 2/16/1999 03:36'!
  21605. envMode
  21606.     ^envMode! !
  21607.  
  21608. !B3DTexture methodsFor: 'accessing' stamp: 'ar 2/16/1999 03:36'!
  21609. envMode: aNumber
  21610.     envMode _ aNumber.! !
  21611.  
  21612. !B3DTexture methodsFor: 'accessing' stamp: 'ar 2/16/1999 03:33'!
  21613. interpolate
  21614.     ^interpolate! !
  21615.  
  21616. !B3DTexture methodsFor: 'accessing' stamp: 'ar 2/16/1999 03:34'!
  21617. interpolate: aBool
  21618.     interpolate _ aBool! !
  21619.  
  21620. !B3DTexture methodsFor: 'accessing' stamp: 'ar 2/16/1999 03:34'!
  21621. wrap
  21622.     ^wrap! !
  21623.  
  21624. !B3DTexture methodsFor: 'accessing' stamp: 'ar 2/16/1999 03:33'!
  21625. wrap: aBool
  21626.     wrap _ aBool! !
  21627.  
  21628. !B3DTexture methodsFor: 'flipping' stamp: 'jsp 3/15/1999 14:20'!
  21629. flipVertically
  21630.     "Flip the texture vertically"
  21631.  
  21632.     | temp h w row |
  21633.  
  21634.     h _ self height.
  21635.     w _ self width.
  21636.  
  21637.     0 to: ((h // 2) - 1) do: [:i |
  21638.         row _ h - i - 1.
  21639.         1 to: w do: [:j |
  21640.                 temp _ bits at: ((i * w) + j).
  21641.                 bits at:  ((i * w) + j) put: (bits at: ((row * w) + j)).
  21642.                 bits at: ((row * w) + j) put: temp.
  21643.                     ].
  21644.                 ].
  21645. ! !
  21646.  
  21647. !B3DTexture methodsFor: 'converting' stamp: 'ar 5/27/1999 17:49'!
  21648. asTexture
  21649.     ^self! !
  21650.  
  21651. !B3DTexture2Array methodsFor: 'accessing' stamp: 'ar 2/6/1999 23:30'!
  21652. at: index put: value
  21653.     value isPoint
  21654.         ifTrue:[super at: index put: (B3DVector2 u: value x v: value y)]
  21655.         ifFalse:[super at: index put: value].
  21656.     ^value! !
  21657.  
  21658. !B3DTexture2Array class methodsFor: 'accessing' stamp: 'ar 2/6/1999 23:31'!
  21659. contentsClass
  21660.     ^B3DVector2! !
  21661.  
  21662. !B3DTransformerPlugin methodsFor: 'primitives' stamp: 'ar 5/22/2000 17:12'!
  21663. b3dInplaceHouseHolderInvert
  21664.     "Primitive. Perform an inplace house holder matrix inversion"
  21665.     | rcvr d x sigma beta sum s m |
  21666.     self export: true.
  21667.     self var: #rcvr declareC:'float *rcvr'.
  21668.     self var: #m declareC:'double m[4][4]'.
  21669.     self var: #x declareC:'double x[4][4] = { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} }'.
  21670.     self var: #d declareC:'double d[4][4]'.
  21671.     self var: #sigma declareC:'double sigma'.
  21672.     self var: #beta declareC:'double beta'.
  21673.     self var: #sum declareC:'double sum'.
  21674.     self var: #s declareC:'double s'.
  21675.  
  21676.     self cCode:'' inSmalltalk:[
  21677.         m _ CArrayAccessor on: 
  21678.                 ((1 to: 4) collect:[:i| CArrayAccessor on: (Array new: 4)]).
  21679.         x _ CArrayAccessor on: (Array
  21680.                 with: (CArrayAccessor on: #(1.0 0.0 0.0 0.0) copy)
  21681.                 with: (CArrayAccessor on: #(0.0 1.0 0.0 0.0) copy)
  21682.                 with: (CArrayAccessor on: #(0.0 0.0 1.0 0.0) copy)
  21683.                 with: (CArrayAccessor on: #(0.0 0.0 0.0 1.0) copy)).
  21684.         d _ CArrayAccessor on: 
  21685.                 ((1 to: 4) collect:[:i| CArrayAccessor on: (Array new: 4)]).
  21686.     ].
  21687.     rcvr _ self stackMatrix: 0.
  21688.     0 to: 3 do:[:i| 0 to: 3 do:[:j|
  21689.         (m at: i) at: j put: (rcvr at: i*4+j)]].
  21690.     0 to: 3 do:[:j|
  21691.         sigma := 0.0.
  21692.         j to: 3 do:[:i| sigma := sigma + (((m at: i) at: j)  * ((m at: i) at: j))].
  21693.         sigma < 1.0e-10 ifTrue:[^interpreterProxy primitiveFail]. "matrix is singular"
  21694.         (((m at: j) at: j) < 0.0) 
  21695.             ifTrue:[ s:= sigma sqrt]
  21696.             ifFalse:[ s:= 0.0 - sigma sqrt].
  21697.         0 to: 3 do:[:r| (d at: j) at: r put: s].
  21698.         beta := 1.0 / ( s * ((m at: j) at: j) - sigma).
  21699.         (m at: j) at: j put: (((m at: j) at: j) - s).
  21700.         "update remaining columns"
  21701.         j+1 to: 3 do:[:k|
  21702.             sum := 0.0.
  21703.             j to: 3 do:[:i| sum := sum + (((m at: i) at: j) * ((m at: i) at: k))].
  21704.             sum := sum * beta.
  21705.             j to: 3 do:[:i| 
  21706.                 (m at: i) at: k put: (((m at: i) at: k) + (((m at: i) at: j) * sum))]].
  21707.         "update vector"
  21708.         0 to: 3 do:[:r|
  21709.             sum := 0.0.
  21710.             j to: 3 do:[:i| 
  21711.                 sum _ sum + (((x at: i) at: r) * ((m at: i) at: j))].
  21712.             sum := sum * beta.
  21713.             j to: 3 do:[:i| 
  21714.                 (x at: i) at: r put:(((x at: i) at: r) + (sum * ((m at: i) at: j)))].
  21715.         ].
  21716.     ].
  21717.     "Now calculate result"
  21718.     0 to: 3 do:[:r|
  21719.         3 to: 0 by: -1 do:[:i|
  21720.             i+1 to: 3 do:[:j|
  21721.                 (x at: i) at: r put: (((x at: i) at: r) - (((x at: j) at: r) * ((m at: i) at: j))) ].
  21722.             (x at: i) at: r put: (((x at: i) at: r) / ((d at: i) at: r))].
  21723.     ].
  21724.     0 to: 3 do:[:i| 0 to: 3 do:[:j|
  21725.         rcvr at: i*4+j put: (self cCoerce: ((x at: i) at: j) to:'float')]].
  21726.     "Return receiver"! !
  21727.  
  21728. !B3DTransformerPlugin methodsFor: 'primitives' stamp: 'ar 2/14/1999 00:02'!
  21729. b3dTransformMatrixWithInto
  21730.     "Transform two matrices into the third"
  21731.     | m1 m2 m3 |
  21732.     self export: true.
  21733.     self inline: false.
  21734.     self var: #m1 declareC:'float *m1'.
  21735.     self var: #m2 declareC:'float *m2'.
  21736.     self var: #m3 declareC:'float *m3'.
  21737.  
  21738.     m3 _ self stackMatrix: 0.
  21739.     m2 _ self stackMatrix: 1.
  21740.     m1 _ self stackMatrix: 2.
  21741.     (m1 = nil) | (m2 = nil) | (m3 = nil) 
  21742.         ifTrue:[^interpreterProxy primitiveFail].
  21743.     m2 == m3 ifTrue:[^interpreterProxy primitiveFail].
  21744.     self transformMatrix: m1 with: m2 into: m3.
  21745.     interpreterProxy pop: 3. "Leave rcvr on stack"! !
  21746.  
  21747. !B3DTransformerPlugin methodsFor: 'primitives' stamp: 'ar 2/14/1999 00:03'!
  21748. b3dTransformPrimitiveNormal
  21749.     "Transform the normal of the given primitive vertex using the argument matrix and rescale the normal if necessary."
  21750.     | pVertex matrix rescale |
  21751.     self export: true.
  21752.     self inline: false.
  21753.     self var: #matrix declareC:'float *matrix'.
  21754.     self var: #pVertex declareC:'float *pVertex'.
  21755.  
  21756.     rescale _ interpreterProxy stackValue: 0.
  21757.     rescale == interpreterProxy nilObject 
  21758.         ifFalse:[rescale _ interpreterProxy booleanValueOf: rescale].
  21759.     matrix _ self stackMatrix: 1.
  21760.     pVertex _ self stackPrimitiveVertex: 2.
  21761.     (matrix = nil) | (pVertex = nil) 
  21762.         ifTrue:[^interpreterProxy primitiveFail].
  21763.     (rescale ~~ true and:[rescale ~~ false])
  21764.         ifTrue:[rescale _ self analyzeMatrix3x3Length: matrix].
  21765.     self transformPrimitiveNormal: pVertex by: matrix rescale: rescale.
  21766.     interpreterProxy pop: 3. "Leave rcvr on stack"! !
  21767.  
  21768. !B3DTransformerPlugin methodsFor: 'primitives' stamp: 'ar 2/14/1999 00:03'!
  21769. b3dTransformPrimitivePosition
  21770.     "Transform the position of the given primitive vertex the given matrix
  21771.     and store the result back inplace."
  21772.     | pVertex matrix |
  21773.     self export: true.
  21774.     self inline: false.
  21775.     self var: #matrix declareC:'float *matrix'.
  21776.     self var: #pVertex declareC:'float *pVertex'.
  21777.  
  21778.     matrix _ self stackMatrix: 0.
  21779.     pVertex _ self stackPrimitiveVertex: 1.
  21780.     (matrix = nil) | (pVertex = nil) 
  21781.         ifTrue:[^interpreterProxy primitiveFail].
  21782.     self transformPrimitivePosition: pVertex by: matrix.
  21783.     interpreterProxy pop: 2. "Leave rcvr on stack"! !
  21784.  
  21785. !B3DTransformerPlugin methodsFor: 'primitives' stamp: 'ar 2/14/1999 00:03'!
  21786. b3dTransformPrimitiveRasterPosition
  21787.     "Transform the position of the given primitive vertex the given matrix
  21788.     and store the result in homogenous coordinates at rasterPos."
  21789.     | pVertex matrix |
  21790.     self export: true.
  21791.     self inline: false.
  21792.     self var: #matrix declareC:'float *matrix'.
  21793.     self var: #pVertex declareC:'float *pVertex'.
  21794.  
  21795.     matrix _ self stackMatrix: 0.
  21796.     pVertex _ self stackPrimitiveVertex: 1.
  21797.     (matrix = nil) | (pVertex = nil) 
  21798.         ifTrue:[^interpreterProxy primitiveFail].
  21799.     self transformPrimitiveRasterPosition: pVertex by: matrix.
  21800.     interpreterProxy pop: 2. "Leave rcvr on stack"! !
  21801.  
  21802. !B3DTransformerPlugin methodsFor: 'primitives' stamp: 'ar 2/14/1999 00:05'!
  21803. b3dTransformVertexBuffer
  21804.     "Transform an entire vertex buffer using the supplied modelview and projection matrix."
  21805.     | flags projectionMatrix modelViewMatrix vtxCount vtxArray |
  21806.     self export: true.
  21807.     self inline: false.
  21808.     self var: #projectionMatrix declareC:'float *projectionMatrix'.
  21809.     self var: #modelViewMatrix declareC:'float *modelViewMatrix'.
  21810.     self var: #vtxArray declareC:'float *vtxArray'.
  21811.  
  21812.     flags _ interpreterProxy stackIntegerValue: 0.
  21813.     projectionMatrix _ self stackMatrix: 1.
  21814.     modelViewMatrix _ self stackMatrix: 2.
  21815.     vtxCount _ interpreterProxy stackIntegerValue: 3.
  21816.     vtxArray _ self stackPrimitiveVertexArray: 4 ofSize: vtxCount.
  21817.     (projectionMatrix = nil) | (modelViewMatrix = nil) | (vtxArray = nil)
  21818.         ifTrue:[^interpreterProxy primitiveFail].
  21819.     interpreterProxy failed ifTrue:[^nil].
  21820.     self transformVB: vtxArray 
  21821.         count: vtxCount 
  21822.         by: modelViewMatrix 
  21823.         and: projectionMatrix 
  21824.         flags: flags.
  21825.     interpreterProxy pop: 5. "Leave rcvr on stack"! !
  21826.  
  21827. !B3DTransformerPlugin methodsFor: 'primitives' stamp: 'ar 2/17/1999 04:31'!
  21828. b3dTransformerVersion
  21829.     "Return the current version of the transformer"
  21830.     self export: true.
  21831.     self inline: false.
  21832.     interpreterProxy pop: 1.
  21833.     interpreterProxy pushInteger: 1.    "Version 1"! !
  21834.  
  21835. !B3DTransformerPlugin methodsFor: 'transforming' stamp: 'ar 2/13/1999 23:45'!
  21836. analyzeMatrix3x3Length: m
  21837.     "Check if the matrix scales normals to non-unit length."
  21838.     | det |
  21839.     self var: #m declareC:'float *m'.
  21840.     self var: #det declareC:'double det'.
  21841.     det _     ((m at: 0) * (m at: 5) * (m at: 10)) -
  21842.             ((m at: 2) * (m at: 5) * (m at: 8)) + 
  21843.             ((m at: 4) * (m at: 9) * (m at: 2)) - 
  21844.             ((m at: 6) * (m at: 9) * (m at: 0)) +
  21845.             ((m at: 8) * (m at: 1) * (m at: 6)) -
  21846.             ((m at: 10) * (m at: 1) * (m at: 4)).
  21847.     ^det < 0.99 or:[det > 1.01]! !
  21848.  
  21849. !B3DTransformerPlugin methodsFor: 'transforming' stamp: 'ar 2/13/1999 23:45'!
  21850. analyzeMatrix: m
  21851.     "Analyze the matrix and return the appropriate flags"
  21852.     | flags |
  21853.     self var: #m declareC:'float *m'.
  21854.     "Check the perspective"
  21855.     flags _ 0.
  21856.     ((m at: 12) = 0.0 and:[(m at: 13) = 0.0 and:[(m at: 14) = 0.0 and:[(m at: 15) = 1.0]]]) ifTrue:[
  21857.         flags _ flags bitOr: FlagM44NoPerspective.
  21858.         "Check translation"
  21859.         ((m at: 3) = 0.0 and:[(m at: 7) = 0.0 and:[(m at: 11) = 0.0]]) ifTrue:[
  21860.             flags _ flags bitOr: FlagM44NoTranslation.
  21861.             "Check for identity"
  21862.             ((m at: 0) = 1.0 and:[(m at: 5) = 1.0 and:[(m at: 10) = 1.0 and:[
  21863.                 (m at: 1) = 0.0 and:[(m at: 2) = 0.0 and:[
  21864.                 (m at: 4) = 0.0 and:[(m at: 6) = 0.0 and:[
  21865.                 (m at: 8) = 0.0 and:[(m at: 9) = 0.0]]]]]]]]) ifTrue:[
  21866.                     flags _ flags bitOr: FlagM44Identity.
  21867.             ].
  21868.         ].
  21869.     ].
  21870.     ^flags! !
  21871.  
  21872. !B3DTransformerPlugin methodsFor: 'transforming' stamp: 'ar 2/13/1999 23:45'!
  21873. transformMatrix: src with: arg into: dst
  21874.     "Transform src with arg into dst.
  21875.     It is allowed that src == dst but not arg == dst"
  21876.     | m1 m2 m3 c1 c2 c3 c4 |
  21877.     self var: #src declareC:'float *src'.
  21878.     self var: #arg declareC:'float *arg'.
  21879.     self var: #dst declareC:'float *dst'.
  21880.     self var: #m1 declareC:'float *m1'.
  21881.     self var: #m2 declareC:'float *m2'.
  21882.     self var: #m3 declareC:'float *m3'.
  21883.     self var: #c1 declareC:'float c1'.
  21884.     self var: #c2 declareC:'float c2'.
  21885.     self var: #c3 declareC:'float c3'.
  21886.     self var: #c4 declareC:'float c4'.
  21887.  
  21888.     m1 _ self cCoerce: src to:'float *'.
  21889.     m2 _ self cCoerce: arg to: 'float *'.
  21890.     m3 _ self cCoerce: dst to: 'float *'.
  21891.  
  21892.     0 to: 3 do:[:i|
  21893.  
  21894.         "Compute next row"
  21895.         c1 _ ((m1 at: 0) * (m2 at: 0)) + ((m1 at: 1) * (m2 at: 4)) +
  21896.                 ((m1 at: 2) * (m2 at: 8)) + ((m1 at: 3) * (m2 at: 12)).
  21897.  
  21898.         c2 _ ((m1 at: 0) * (m2 at: 1)) + ((m1 at: 1) * (m2 at: 5)) +
  21899.                 ((m1 at: 2) * (m2 at: 9)) + ((m1 at: 3) * (m2 at: 13)).
  21900.  
  21901.         c3 _ ((m1 at: 0) * (m2 at: 2)) + ((m1 at: 1) * (m2 at: 6)) +
  21902.                 ((m1 at: 2) * (m2 at: 10)) + ((m1 at: 3) * (m2 at: 14)).
  21903.  
  21904.         c4 _ ((m1 at: 0) * (m2 at: 3)) + ((m1 at: 1) * (m2 at: 7)) +
  21905.                 ((m1 at: 2) * (m2 at: 11)) + ((m1 at: 3) * (m2 at: 15)).
  21906.  
  21907.         "Store result"
  21908.         m3 at: 0 put: c1.
  21909.         m3 at: 1 put: c2.
  21910.         m3 at: 2 put: c3.
  21911.         m3 at: 3 put: c4.
  21912.  
  21913.         "Skip src and dst to next row"
  21914.         m1 _ m1 + 4.
  21915.         m3 _ m3 + 4.
  21916.     ].
  21917. ! !
  21918.  
  21919. !B3DTransformerPlugin methodsFor: 'transforming' stamp: 'ar 4/17/1999 22:22'!
  21920. transformPrimitiveNormal: pVertex by: matrix rescale: rescale
  21921.     "Transform the normal of the given primitive vertex"
  21922.     | x y z rx ry rz dot |
  21923.     self var: #pVertex declareC:'float *pVertex'.
  21924.     self var: #matrix declareC:'float *matrix'.
  21925.     self var: #x declareC:'double x'.
  21926.     self var: #y declareC:'double y'.
  21927.     self var: #z declareC:'double z'.
  21928.     self var: #rx declareC:'double rx'.
  21929.     self var: #ry declareC:'double ry'.
  21930.     self var: #rz declareC:'double rz'.
  21931.     self var: #dot declareC:'double dot'.
  21932.  
  21933.     x _ pVertex at: PrimVtxNormalX.
  21934.     y _ pVertex at: PrimVtxNormalY.
  21935.     z _ pVertex at: PrimVtxNormalZ.
  21936.  
  21937.     rx _ (x * (matrix at: 0)) + (y * (matrix at: 1)) + (z * (matrix at: 2)).
  21938.     ry _ (x * (matrix at: 4)) + (y * (matrix at: 5)) + (z * (matrix at: 6)).
  21939.     rz _ (x * (matrix at: 8)) + (y * (matrix at: 9)) + (z * (matrix at: 10)).
  21940.  
  21941.     rescale ifTrue:[
  21942.         dot _ (rx * rx) + (ry * ry) + (rz * rz).
  21943.         dot < 1.0e-20 
  21944.             ifTrue:[rx _ ry _ rz _ 0.0]
  21945.             ifFalse:[dot = 1.0 ifFalse:[dot _ 1.0 / dot sqrt.
  21946.                                     rx _ rx * dot. ry _ ry * dot. rz _ rz * dot]]].
  21947.  
  21948.     pVertex at: PrimVtxNormalX put: (self cCoerce: rx to:'float').
  21949.     pVertex at: PrimVtxNormalY put: (self cCoerce: ry to:'float').
  21950.     pVertex at: PrimVtxNormalZ put: (self cCoerce: rz to:'float').
  21951. ! !
  21952.  
  21953. !B3DTransformerPlugin methodsFor: 'transforming' stamp: 'ar 4/17/1999 22:24'!
  21954. transformPrimitivePosition: pVertex by: matrix
  21955.     "Transform the normal of the given primitive vertex"
  21956.     | x y z rx ry rz rw |
  21957.     self var: #pVertex declareC:'float *pVertex'.
  21958.     self var: #matrix declareC:'float *matrix'.
  21959.     self var: #x declareC:'double x'.
  21960.     self var: #y declareC:'double y'.
  21961.     self var: #z declareC:'double z'.
  21962.     self var: #rx declareC:'double rx'.
  21963.     self var: #ry declareC:'double ry'.
  21964.     self var: #rz declareC:'double rz'.
  21965.     self var: #rw declareC:'double rw'.
  21966.  
  21967.     x _ pVertex at: PrimVtxPositionX.
  21968.     y _ pVertex at: PrimVtxPositionY.
  21969.     z _ pVertex at: PrimVtxPositionZ.
  21970.  
  21971.     rx _ (x * (matrix at: 0)) + (y * (matrix at: 1)) + (z * (matrix at: 2)) + (matrix at: 3).
  21972.     ry _ (x * (matrix at: 4)) + (y * (matrix at: 5)) + (z * (matrix at: 6)) + (matrix at: 7).
  21973.     rz _ (x * (matrix at: 8)) + (y * (matrix at: 9)) + (z * (matrix at: 10)) + (matrix at: 11).
  21974.     rw _ (x * (matrix at: 12)) + (y * (matrix at: 13)) + (z * (matrix at: 14)) + (matrix at: 15).
  21975.  
  21976.     rw = 1.0 ifTrue:[
  21977.         pVertex at: PrimVtxPositionX put: (self cCoerce: rx to: 'float').
  21978.         pVertex at: PrimVtxPositionY put: (self cCoerce: ry to:'float').
  21979.         pVertex at: PrimVtxPositionZ put: (self cCoerce: rz to: 'float').
  21980.     ] ifFalse:[
  21981.         rw = 0.0 
  21982.             ifTrue:[rw _ 0.0]
  21983.             ifFalse:[rw _ 1.0 / rw].
  21984.         pVertex at: PrimVtxPositionX put: (self cCoerce: rx*rw to:'float').
  21985.         pVertex at: PrimVtxPositionY put: (self cCoerce: ry*rw to:'float').
  21986.         pVertex at: PrimVtxPositionZ put: (self cCoerce: rz*rw to: 'float').
  21987.     ].
  21988. ! !
  21989.  
  21990. !B3DTransformerPlugin methodsFor: 'transforming' stamp: 'ar 4/17/1999 22:24'!
  21991. transformPrimitivePositionFast: pVertex by: matrix
  21992.     "Transform the position of the given primitive vertex assuming that 
  21993.     matrix a41 = a42 = a43 = 0.0 and a44 = 1.0"
  21994.     | x y z rx ry rz |
  21995.     self var: #pVertex declareC:'float *pVertex'.
  21996.     self var: #matrix declareC:'float *matrix'.
  21997.     self var: #x declareC:'double x'.
  21998.     self var: #y declareC:'double y'.
  21999.     self var: #z declareC:'double z'.
  22000.     self var: #rx declareC:'double rx'.
  22001.     self var: #ry declareC:'double ry'.
  22002.     self var: #rz declareC:'double rz'.
  22003.  
  22004.     x _ pVertex at: PrimVtxPositionX.
  22005.     y _ pVertex at: PrimVtxPositionY.
  22006.     z _ pVertex at: PrimVtxPositionZ.
  22007.  
  22008.     rx _ (x * (matrix at: 0)) + (y * (matrix at: 1)) + (z * (matrix at: 2)) + (matrix at: 3).
  22009.     ry _ (x * (matrix at: 4)) + (y * (matrix at: 5)) + (z * (matrix at: 6)) + (matrix at: 7).
  22010.     rz _ (x * (matrix at: 8)) + (y * (matrix at: 9)) + (z * (matrix at: 10)) + (matrix at: 11).
  22011.  
  22012.     pVertex at: PrimVtxPositionX put: (self cCoerce: rx to: 'float').
  22013.     pVertex at: PrimVtxPositionY put: (self cCoerce: ry to: 'float').
  22014.     pVertex at: PrimVtxPositionZ put: (self cCoerce: rz to: 'float').! !
  22015.  
  22016. !B3DTransformerPlugin methodsFor: 'transforming' stamp: 'ar 4/17/1999 22:25'!
  22017. transformPrimitivePositionFaster: pVertex by: matrix
  22018.     "Transform the position of the given primitive vertex assuming that 
  22019.     matrix a14 = a24 = a34 = a41 = a42 = a43 = 0.0 and a44 = 1.0"
  22020.     | x y z rx ry rz |
  22021.     self var: #pVertex declareC:'float *pVertex'.
  22022.     self var: #matrix declareC:'float *matrix'.
  22023.     self var: #x declareC:'double x'.
  22024.     self var: #y declareC:'double y'.
  22025.     self var: #z declareC:'double z'.
  22026.     self var: #rx declareC:'double rx'.
  22027.     self var: #ry declareC:'double ry'.
  22028.     self var: #rz declareC:'double rz'.
  22029.  
  22030.     x _ pVertex at: PrimVtxPositionX.
  22031.     y _ pVertex at: PrimVtxPositionY.
  22032.     z _ pVertex at: PrimVtxPositionZ.
  22033.  
  22034.     rx _ (x * (matrix at: 0)) + (y * (matrix at: 1)) + (z * (matrix at: 2)).
  22035.     ry _ (x * (matrix at: 4)) + (y * (matrix at: 5)) + (z * (matrix at: 6)).
  22036.     rz _ (x * (matrix at: 8)) + (y * (matrix at: 9)) + (z * (matrix at: 10)).
  22037.  
  22038.     pVertex at: PrimVtxPositionX put: (self cCoerce: rx to:'float').
  22039.     pVertex at: PrimVtxPositionY put: (self cCoerce: ry to:'float').
  22040.     pVertex at: PrimVtxPositionZ put: (self cCoerce: rz to: 'float').! !
  22041.  
  22042. !B3DTransformerPlugin methodsFor: 'transforming' stamp: 'ar 4/17/1999 22:26'!
  22043. transformPrimitiveRasterPosition: pVertex by: matrix
  22044.     "Transform the normal of the given primitive vertex"
  22045.     | x y z rx ry rz rw |
  22046.     self var: #pVertex declareC:'float *pVertex'.
  22047.     self var: #matrix declareC:'float *matrix'.
  22048.     self var: #x declareC:'double x'.
  22049.     self var: #y declareC:'double y'.
  22050.     self var: #z declareC:'double z'.
  22051.     self var: #rx declareC:'double rx'.
  22052.     self var: #ry declareC:'double ry'.
  22053.     self var: #rz declareC:'double rz'.
  22054.     self var: #rw declareC:'double rw'.
  22055.  
  22056.     x _ pVertex at: PrimVtxPositionX.
  22057.     y _ pVertex at: PrimVtxPositionY.
  22058.     z _ pVertex at: PrimVtxPositionZ.
  22059.  
  22060.     rx _ (x * (matrix at: 0)) + (y * (matrix at: 1)) + (z * (matrix at: 2)) + (matrix at: 3).
  22061.     ry _ (x * (matrix at: 4)) + (y * (matrix at: 5)) + (z * (matrix at: 6)) + (matrix at: 7).
  22062.     rz _ (x * (matrix at: 8)) + (y * (matrix at: 9)) + (z * (matrix at: 10)) + (matrix at: 11).
  22063.     rw _ (x * (matrix at: 12)) + (y * (matrix at: 13)) + (z * (matrix at: 14)) + (matrix at: 15).
  22064.  
  22065.     pVertex at: PrimVtxRasterPosX put: (self cCoerce: rx to:'float').
  22066.     pVertex at: PrimVtxRasterPosY put: (self cCoerce: ry to:'float').
  22067.     pVertex at: PrimVtxRasterPosZ put: (self cCoerce: rz to:'float').
  22068.     pVertex at: PrimVtxRasterPosW put: (self cCoerce: rw to:'float').
  22069. ! !
  22070.  
  22071. !B3DTransformerPlugin methodsFor: 'transforming' stamp: 'ar 2/13/1999 23:47'!
  22072. transformVB: vtxArray count: vtxCount by: modelViewMatrix and: projectionMatrix flags: flags
  22073.     "Transform the entire vertex array by the given matrices"
  22074.     "TODO: Check the actual trade-offs between vtxCount and analyzing"
  22075.     | mvFlags prFlags pVertex hasNormals rescale |
  22076.     self var: #projectionMatrix declareC:'float *projectionMatrix'.
  22077.     self var: #modelViewMatrix declareC:'float *modelViewMatrix'.
  22078.     self var: #vtxArray declareC:'float *vtxArray'.
  22079.     self var: #pVertex declareC:'float *pVertex'.
  22080.  
  22081.     "Analyze the matrices for better performance"
  22082.     mvFlags _ self analyzeMatrix: modelViewMatrix.
  22083.     prFlags _ self analyzeMatrix: projectionMatrix.
  22084.  
  22085.     pVertex _ self cCoerce: vtxArray to: 'float *'.
  22086.     hasNormals _ flags anyMask: VBVtxHasNormals.
  22087.  
  22088.     "Check if we have to rescale the normals"
  22089.     hasNormals ifTrue:[
  22090.         (mvFlags anyMask: FlagM44Identity)
  22091.             ifTrue:[rescale _ false]
  22092.             ifFalse:[rescale _ self analyzeMatrix3x3Length: modelViewMatrix]].
  22093.  
  22094.     "<---- NOTE: The most likely case goes first ---->"
  22095.     ((mvFlags anyMask: FlagM44NoPerspective) and:[prFlags = 0]) ifTrue:[
  22096.         "Modelview matrix has no perspective part and projection is not optimized"
  22097.         (mvFlags = FlagM44NoTranslation) = 0 ifTrue:[
  22098.             "Modelview matrix with translation"
  22099.             1 to: vtxCount do:[:i|
  22100.                 hasNormals ifTrue:[self transformPrimitiveNormal: pVertex by: modelViewMatrix rescale: rescale].
  22101.                 self transformPrimitivePositionFast: pVertex by: modelViewMatrix.
  22102.                 self transformPrimitiveRasterPosition: pVertex by: projectionMatrix.
  22103.                 pVertex _ pVertex + PrimVertexSize].
  22104.         ] ifFalse:[
  22105.             "Modelview matrix without translation"
  22106.             1 to: vtxCount do:[:i|
  22107.                 hasNormals ifTrue:[self transformPrimitiveNormal: pVertex by: modelViewMatrix rescale: rescale].
  22108.                 self transformPrimitivePositionFaster: pVertex by: modelViewMatrix.
  22109.                 self transformPrimitiveRasterPosition: pVertex by: projectionMatrix.
  22110.                 pVertex _ pVertex + PrimVertexSize].
  22111.         ].
  22112.         ^nil]. "done"
  22113.     "<---- End of most likely case ---->"
  22114.  
  22115.     ((mvFlags bitAnd: prFlags) anyMask: FlagM44Identity) ifTrue:[
  22116.         "If both are identity matrices just copy entries"
  22117.         1 to: vtxCount do:[:i|
  22118.             pVertex at: PrimVtxRasterPosX put: (pVertex at: PrimVtxPositionX).
  22119.             pVertex at: PrimVtxRasterPosY put: (pVertex at: PrimVtxPositionY).
  22120.             pVertex at: PrimVtxRasterPosZ put: (pVertex at: PrimVtxPositionZ).
  22121.             pVertex at: PrimVtxRasterPosW put: 1.0.
  22122.             pVertex _ pVertex + PrimVertexSize].
  22123.         ^nil]."done"
  22124.  
  22125.     (mvFlags anyMask: FlagM44Identity) ifTrue:[
  22126.         "If model view matrix is identity just perform projection"
  22127.         1 to: vtxCount do:[:i|
  22128.             self transformPrimitiveRasterPosition: pVertex by: projectionMatrix.
  22129.             pVertex _ pVertex + PrimVertexSize].
  22130.         ^nil]. "done"
  22131.  
  22132.     "<--- modelview matrix not identity --->"
  22133.  
  22134.     (prFlags anyMask: FlagM44Identity) ifTrue:[
  22135.         "If projection matrix is identity just transform and copy.
  22136.         Note: This case is not very likely so it's not been unrolled."
  22137.         1 to: vtxCount do:[:i|
  22138.             hasNormals ifTrue:[self transformPrimitiveNormal: pVertex by: modelViewMatrix rescale: rescale].
  22139.             mvFlags = (FlagM44NoPerspective + FlagM44NoPerspective) ifTrue:[
  22140.                 self transformPrimitivePositionFaster: pVertex by: modelViewMatrix.
  22141.             ] ifFalse:[mvFlags = FlagM44NoPerspective ifTrue:[
  22142.                 self transformPrimitivePositionFast: pVertex by: modelViewMatrix.
  22143.             ] ifFalse:[
  22144.                 self transformPrimitivePosition: pVertex by: modelViewMatrix.
  22145.             ]].
  22146.             pVertex at: PrimVtxRasterPosX put: (pVertex at: PrimVtxPositionX).
  22147.             pVertex at: PrimVtxRasterPosY put: (pVertex at: PrimVtxPositionY).
  22148.             pVertex at: PrimVtxRasterPosZ put: (pVertex at: PrimVtxPositionZ).
  22149.             pVertex at: PrimVtxRasterPosW put: 1.0.
  22150.             pVertex _ pVertex + PrimVertexSize].
  22151.         ^nil]. "done"
  22152.  
  22153.     "<----- None of the matrices is identity ---->"
  22154.  
  22155.     "Generic transformation"
  22156.     1 to: vtxCount do:[:i|
  22157.         hasNormals ifTrue:[self transformPrimitiveNormal: pVertex by: modelViewMatrix rescale: rescale].
  22158.         self transformPrimitivePosition: pVertex by: modelViewMatrix.
  22159.         self transformPrimitiveRasterPosition: pVertex by: projectionMatrix.
  22160.         pVertex _ pVertex + PrimVertexSize].! !
  22161.  
  22162. I represent simple 2D coordinates in the Balloon 3D framework. I may be used to represent both, 2D points and 2D texture coordinates. !
  22163. !B3DVector2 methodsFor: 'initialize' stamp: 'ar 2/6/1999 23:30'!
  22164. u: uValue v: vValue
  22165.     self u: uValue.
  22166.     self v: vValue.! !
  22167.  
  22168. !B3DVector2 methodsFor: 'initialize' stamp: 'ar 5/4/2000 15:50'!
  22169. x: uValue y: vValue
  22170.     self x: uValue.
  22171.     self y: vValue.! !
  22172.  
  22173. !B3DVector2 methodsFor: 'accessing' stamp: 'ar 2/6/1999 23:26'!
  22174. u
  22175.     ^self floatAt: 1! !
  22176.  
  22177. !B3DVector2 methodsFor: 'accessing' stamp: 'ar 2/6/1999 23:27'!
  22178. u: aFloat
  22179.     self floatAt: 1 put: aFloat! !
  22180.  
  22181. !B3DVector2 methodsFor: 'accessing' stamp: 'ar 2/6/1999 23:27'!
  22182. v
  22183.     ^self floatAt: 2! !
  22184.  
  22185. !B3DVector2 methodsFor: 'accessing' stamp: 'ar 2/6/1999 23:27'!
  22186. v: aFloat
  22187.     self floatAt: 2 put: aFloat! !
  22188.  
  22189. !B3DVector2 methodsFor: 'accessing' stamp: 'ar 2/7/1999 02:58'!
  22190. x
  22191.     ^self at: 1! !
  22192.  
  22193. !B3DVector2 methodsFor: 'accessing' stamp: 'ar 5/4/2000 16:00'!
  22194. x: aFloat
  22195.     self floatAt: 1 put: aFloat! !
  22196.  
  22197. !B3DVector2 methodsFor: 'accessing' stamp: 'ar 2/7/1999 02:58'!
  22198. y
  22199.     ^self at: 2! !
  22200.  
  22201. !B3DVector2 methodsFor: 'accessing' stamp: 'ar 5/4/2000 16:00'!
  22202. y: aFloat
  22203.     self floatAt: 2 put: aFloat! !
  22204.  
  22205. !B3DVector2 methodsFor: 'converting' stamp: 'ar 2/13/1999 20:03'!
  22206. asPoint
  22207.     ^self x @ self y! !
  22208.  
  22209. !B3DVector2 class methodsFor: 'instance creation' stamp: 'ar 2/6/1999 23:31'!
  22210. numElements
  22211.     ^2! !
  22212.  
  22213. !B3DVector2 class methodsFor: 'instance creation' stamp: 'ar 2/6/1999 23:31'!
  22214. u: uValue v: vValue
  22215.     ^self new u: uValue v: vValue! !
  22216.  
  22217. !B3DVector2 class methodsFor: 'instance creation' stamp: 'ar 5/4/2000 15:49'!
  22218. x: uValue y: vValue
  22219.     ^self new x: uValue y: vValue! !
  22220.  
  22221. !B3DVector2Array class methodsFor: 'instance creation' stamp: 'ar 5/4/2000 15:59'!
  22222. contentsClass
  22223.     ^B3DVector2! !
  22224.  
  22225. I represent simple 3D coordinates, used throughout the entire Balloon 3D engine.!
  22226. !B3DVector3 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:24'!
  22227. x
  22228.     ^self at: 1! !
  22229.  
  22230. !B3DVector3 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:24'!
  22231. x: aFloat
  22232.     self at: 1 put: aFloat! !
  22233.  
  22234. !B3DVector3 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:24'!
  22235. y
  22236.     ^self at: 2! !
  22237.  
  22238. !B3DVector3 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:24'!
  22239. y: aFloat
  22240.     self at: 2 put: aFloat! !
  22241.  
  22242. !B3DVector3 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:24'!
  22243. z
  22244.     ^self at: 3! !
  22245.  
  22246. !B3DVector3 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:24'!
  22247. z: aFloat
  22248.     self at: 3 put: aFloat! !
  22249.  
  22250. !B3DVector3 methodsFor: 'vector functions'!
  22251. cross: aVector 
  22252.     "calculate the cross product from the receiver with aVector"
  22253.     ^self species
  22254.         x: self y * aVector z - (aVector y * self z)
  22255.         y: self z * aVector x - (aVector z * self x)
  22256.         z: self x * aVector y - (aVector x * self y)! !
  22257.  
  22258. !B3DVector3 methodsFor: 'vector functions'!
  22259. length: newLength
  22260.     self safelyNormalize *= newLength! !
  22261.  
  22262. !B3DVector3 methodsFor: 'vector functions' stamp: 'ar 2/6/1999 00:32'!
  22263. max: aVector
  22264.     ^B3DVector3 
  22265.         x: (self x max: aVector x)
  22266.         y: (self y max: aVector y)
  22267.         z: (self z max: aVector z)! !
  22268.  
  22269. !B3DVector3 methodsFor: 'vector functions' stamp: 'ar 2/6/1999 00:31'!
  22270. min: aVector
  22271.     ^B3DVector3 
  22272.         x: (self x min: aVector x)
  22273.         y: (self y min: aVector y)
  22274.         z: (self z min: aVector z)! !
  22275.  
  22276. !B3DVector3 methodsFor: 'vector functions'!
  22277. normalize
  22278.     self /= self length! !
  22279.  
  22280. !B3DVector3 methodsFor: 'vector functions'!
  22281. normalized
  22282.     ^self / self length! !
  22283.  
  22284. !B3DVector3 methodsFor: 'vector functions' stamp: 'ar 2/7/1999 00:43'!
  22285. safelyNormalize
  22286.     "Safely normalize the receiver, e.g. check if the length is non-zero"
  22287.     | length |
  22288.     length _ self length.
  22289.     length = 1.0 ifTrue:[^self].
  22290.     length = 0.0 ifFalse:[self /= length].! !
  22291.  
  22292. !B3DVector3 methodsFor: 'vector functions'!
  22293. safelyNormalized
  22294.     "Safely normalize the receiver, e.g. check if the length is non-zero"
  22295.     ^self copy safelyNormalize! !
  22296.  
  22297. !B3DVector3 methodsFor: 'vector functions'!
  22298. squaredLength: newLength
  22299.     self length: newLength sqrt! !
  22300.  
  22301. !B3DVector3 methodsFor: 'private'!
  22302. privateLoadFrom: srcObject
  22303.     self x: srcObject x y: srcObject y z: srcObject z.! !
  22304.  
  22305. !B3DVector3 methodsFor: 'initialize'!
  22306. x: x y: y z: z
  22307.     self x: x.
  22308.     self y: y.
  22309.     self z: z.! !
  22310.  
  22311. !B3DVector3 methodsFor: 'converting' stamp: 'ar 2/6/1999 00:06'!
  22312. asB3DVector3
  22313.     ^self! !
  22314.  
  22315. !B3DVector3 methodsFor: 'converting' stamp: 'ar 2/6/1999 00:07'!
  22316. asB3DVector4
  22317.     ^B3DVector4 x: self x y: self y z: self z w: 1.0! !
  22318.  
  22319. !B3DVector3 methodsFor: 'interpolating' stamp: 'jsp 2/9/1999 11:17'!
  22320. interpolateTo: end at: amountDone
  22321.     "Interpolates a new vector based on the instance vector, the end state vector, and the amount already done (between 0 and 1)."
  22322.  
  22323.     | tX tY tZ |
  22324.     tX _ self x.
  22325.     tY _ self y.
  22326.     tZ _ self z.
  22327.  
  22328.     ^ (B3DVector3 x: (tX + (((end x) - tX) * amountDone))
  22329.                 y: (tY + (((end y) - tY) * amountDone))
  22330.                 z: (tZ + (((end z) - tZ) * amountDone))).
  22331. ! !
  22332.  
  22333. !B3DVector3 methodsFor: 'testing' stamp: 'laza 3/16/2000 16:30'!
  22334. isZero
  22335.     ^self = B3DVector3 zero! !
  22336.  
  22337. !B3DVector3 class methodsFor: 'instance creation' stamp: 'ar 2/1/1999 21:23'!
  22338. numElements
  22339.     ^3! !
  22340.  
  22341. !B3DVector3 class methodsFor: 'instance creation' stamp: 'ar 2/15/1999 02:56'!
  22342. value: aFloat
  22343.     ^self x: aFloat y: aFloat z: aFloat! !
  22344.  
  22345. !B3DVector3 class methodsFor: 'instance creation'!
  22346. x: x y: y z: z
  22347.     ^self new x: x y: y z: z! !
  22348.  
  22349. !B3DVector3 class methodsFor: 'instance creation'!
  22350. zero
  22351.     ^self new! !
  22352.  
  22353. !B3DVector3Array class methodsFor: 'instance creation' stamp: 'ar 2/5/1999 22:51'!
  22354. contentsClass
  22355.     ^B3DVector3! !
  22356.  
  22357. I represent 3D points in homogenous coordinates.!
  22358. !B3DVector4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:16'!
  22359. w
  22360.     ^self at: 4! !
  22361.  
  22362. !B3DVector4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:17'!
  22363. w: aFloat
  22364.     self at: 4 put: aFloat! !
  22365.  
  22366. !B3DVector4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:16'!
  22367. x
  22368.     ^self at: 1! !
  22369.  
  22370. !B3DVector4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:17'!
  22371. x: aFloat
  22372.     self at: 1 put: aFloat! !
  22373.  
  22374. !B3DVector4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:16'!
  22375. y
  22376.     ^self at: 2! !
  22377.  
  22378. !B3DVector4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:17'!
  22379. y: aFloat
  22380.     self at: 2 put: aFloat! !
  22381.  
  22382. !B3DVector4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:16'!
  22383. z
  22384.     ^self at: 3! !
  22385.  
  22386. !B3DVector4 methodsFor: 'accessing' stamp: 'ar 2/1/1999 21:17'!
  22387. z: aFloat
  22388.     self at: 3 put: aFloat! !
  22389.  
  22390. !B3DVector4 methodsFor: 'private'!
  22391. privateLoadFrom: srcObject
  22392.     self x: srcObject x y: srcObject y z: srcObject z w: srcObject w.! !
  22393.  
  22394. !B3DVector4 methodsFor: 'initialize'!
  22395. x: x y: y z: z w: w
  22396.     self x: x.
  22397.     self y: y.
  22398.     self z: z.
  22399.     self w: w.! !
  22400.  
  22401. !B3DVector4 methodsFor: 'converting' stamp: 'ar 2/6/1999 00:08'!
  22402. asB3DVector3
  22403.     | wValue |
  22404.     wValue _ self w.
  22405.     wValue = 0.0 ifTrue:[^B3DVector3 zero].
  22406.     ^B3DVector3 x: self x / wValue y: self y / wValue z: self z / wValue! !
  22407.  
  22408. !B3DVector4 methodsFor: 'converting' stamp: 'ar 2/6/1999 00:07'!
  22409. asB3DVector4
  22410.     ^self! !
  22411.  
  22412. !B3DVector4 class methodsFor: 'instance creation' stamp: 'ar 2/1/1999 21:21'!
  22413. numElements
  22414.     ^4! !
  22415.  
  22416. !B3DVector4 class methodsFor: 'instance creation'!
  22417. x: x y: y z: z
  22418.     ^self x: x y: y z: z w: 1.0! !
  22419.  
  22420. !B3DVector4 class methodsFor: 'instance creation'!
  22421. x: x y: y z: z w: w
  22422.     ^self new x: x y: y z: z w: w! !
  22423.  
  22424. !B3DVector4 class methodsFor: 'instance creation'!
  22425. zero
  22426.     ^self new! !
  22427.  
  22428. I represent the vertex buffer passed on throughout the entire Balloon 3D rendering pipeline. I store all information that may be needed by either part of the pipeline.
  22429.  
  22430. Instance variables:
  22431.     current         <B3DPrimitiveVertex>    Tracking the current attributes of vertices
  22432.     vertexArray     <B3DPrimitiveVertexArray>    Container for all primitive vertices
  22433.     vertexCount     <Integer>    The number of vertices in the vertex array
  22434.     indexArray         <WordArray>    Stores the indexes for indexed primitives
  22435.     indexCount         <Integer>    Number of indexes in the index array
  22436.     primitive         <Integer>    The type of primitive currently in the buffer
  22437.     clipFlags         <Integer>    The clip mask of the vertices in the buffer
  22438.     flags            <Integer>    Various state flags !
  22439. !B3DVertexBuffer methodsFor: 'accessing' stamp: 'ar 2/5/1999 18:44'!
  22440. clipFlags
  22441.     ^clipFlags! !
  22442.  
  22443. !B3DVertexBuffer methodsFor: 'accessing' stamp: 'ar 2/5/1999 18:44'!
  22444. clipFlags: aNumber
  22445.     clipFlags _ aNumber! !
  22446.  
  22447. !B3DVertexBuffer methodsFor: 'accessing' stamp: 'ar 2/8/1999 17:39'!
  22448. flags
  22449.     ^flags! !
  22450.  
  22451. !B3DVertexBuffer methodsFor: 'accessing' stamp: 'ar 2/8/1999 17:40'!
  22452. flags: newFlags
  22453.     "Note: should be used with CARE!!"
  22454.     flags _ newFlags! !
  22455.  
  22456. !B3DVertexBuffer methodsFor: 'accessing' stamp: 'ar 2/7/1999 02:13'!
  22457. indexArray
  22458.     ^indexArray! !
  22459.  
  22460. !B3DVertexBuffer methodsFor: 'accessing' stamp: 'ar 2/7/1999 02:13'!
  22461. indexArray: aWordArray
  22462.     indexArray _ aWordArray! !
  22463.  
  22464. !B3DVertexBuffer methodsFor: 'accessing' stamp: 'ar 2/7/1999 02:13'!
  22465. indexCount
  22466.     ^indexCount! !
  22467.  
  22468. !B3DVertexBuffer methodsFor: 'accessing' stamp: 'ar 2/7/1999 02:14'!
  22469. indexCount: aNumber
  22470.     indexCount _ aNumber! !
  22471.  
  22472. !B3DVertexBuffer methodsFor: 'accessing' stamp: 'ar 2/5/1999 18:48'!
  22473. primitive
  22474.     ^primitive! !
  22475.  
  22476. !B3DVertexBuffer methodsFor: 'accessing' stamp: 'ar 2/5/1999 18:49'!
  22477. primitive: aNumber
  22478.     primitive _ aNumber.! !
  22479.  
  22480. !B3DVertexBuffer methodsFor: 'accessing'!
  22481. vertexArray
  22482.     ^vertexArray! !
  22483.  
  22484. !B3DVertexBuffer methodsFor: 'accessing' stamp: 'ar 2/5/1999 18:44'!
  22485. vertexArray: aB3DVertexArray
  22486.     vertexArray _ aB3DVertexArray! !
  22487.  
  22488. !B3DVertexBuffer methodsFor: 'accessing'!
  22489. vertexCount
  22490.     ^vertexCount! !
  22491.  
  22492. !B3DVertexBuffer methodsFor: 'accessing' stamp: 'ar 2/5/1999 18:44'!
  22493. vertexCount: aNumber
  22494.     vertexCount _ aNumber! !
  22495.  
  22496. !B3DVertexBuffer methodsFor: 'initialize' stamp: 'ar 2/13/1999 20:24'!
  22497. initialize
  22498.     vertexArray _ B3DPrimitiveVertexArray new: 100.
  22499.     vertexCount _ 0.
  22500.     indexArray _ WordArray new: 100.
  22501.     indexCount _ 0.
  22502.     current _ B3DPrimitiveVertex new.
  22503.     flags _ 0.
  22504.     primitive _ nil.! !
  22505.  
  22506. !B3DVertexBuffer methodsFor: 'initialize' stamp: 'ar 2/13/1999 20:24'!
  22507. reset
  22508.     vertexCount _ 0.
  22509.     indexCount _ 0.! !
  22510.  
  22511. !B3DVertexBuffer methodsFor: 'attributes'!
  22512. color
  22513.     ^current color! !
  22514.  
  22515. !B3DVertexBuffer methodsFor: 'attributes'!
  22516. color: aColor
  22517.     current color: aColor! !
  22518.  
  22519. !B3DVertexBuffer methodsFor: 'attributes' stamp: 'ar 2/15/1999 00:09'!
  22520. loadIndexed: idxArray vertices: vertices normals: normals colors: colors texCoords: texCoords
  22521.     | vtxSize idxSize maxVtx maxIdx |
  22522.     "Check the size of the vertex array"
  22523.     vtxSize _ vertices size.    
  22524.     vertexCount + vtxSize >= vertexArray size ifTrue:[
  22525.         self growVertexArray: (vtxSize + vertexArray size + 100).
  22526.     ].
  22527.     "Check the size of the index array"
  22528.     idxSize _ idxArray basicSize.
  22529.     indexCount + idxSize >= indexArray size ifTrue:[
  22530.         self growIndexArray: (idxSize + indexArray size + 100).
  22531.     ].
  22532.     "Check the sizes of normals, colors, and texCoords"
  22533.     (normals notNil and:[vtxSize ~= normals size]) ifTrue:[^self errorSizeMismatch].
  22534.     (colors notNil and:[vtxSize ~= colors size]) ifTrue:[^self errorSizeMismatch].
  22535.     (texCoords notNil and:[vtxSize ~= texCoords size]) ifTrue:[^self errorSizeMismatch].
  22536.     "Turn off the appropriate flags if no attributes are given.
  22537.     Default to having vertex normals and texture coords."
  22538.     flags _ flags bitOr: (VBVtxHasNormals + VBVtxHasTexCoords).
  22539.     "Turn off tracking flags if no colors are given"
  22540.     colors ifNil:[flags _ flags bitAnd: VBNoTrackMask].
  22541.     normals ifNil:[flags _ flags bitAnd: VBVtxHasNormals bitInvert32].
  22542.     texCoords ifNil:[flags _ flags bitAnd: VBVtxHasTexCoords bitInvert32].
  22543.     "Load the vertices"
  22544.     maxVtx _ self primLoadVB: vertexArray
  22545.                     startingAt: vertexCount
  22546.                     vertices: vertices 
  22547.                     normals: normals 
  22548.                     colors: colors 
  22549.                     texCoords: texCoords 
  22550.                     count: vtxSize
  22551.                     default: current.
  22552.     "Load the indexes"
  22553.     maxIdx _ self 
  22554.                 primLoadIndexArrayInto: indexArray 
  22555.                 startingAt: indexCount 
  22556.                 from: idxArray 
  22557.                 count: idxSize 
  22558.                 max: maxVtx 
  22559.                 offset: vertexCount.
  22560.     "Adjust the size of the vertex array and the index array"
  22561.     vertexCount _ vertexCount + maxVtx.
  22562.     indexCount _ indexCount + maxIdx.! !
  22563.  
  22564. !B3DVertexBuffer methodsFor: 'attributes'!
  22565. normal
  22566.     ^current normal! !
  22567.  
  22568. !B3DVertexBuffer methodsFor: 'attributes'!
  22569. normal: aVector
  22570.     current normal: aVector! !
  22571.  
  22572. !B3DVertexBuffer methodsFor: 'attributes'!
  22573. texCoords
  22574.     ^current texCoords! !
  22575.  
  22576. !B3DVertexBuffer methodsFor: 'attributes'!
  22577. texCoords: aVector
  22578.     current texCoords: aVector! !
  22579.  
  22580. !B3DVertexBuffer methodsFor: 'attributes' stamp: 'ar 2/8/1999 17:37'!
  22581. trackAmbientColor: aBool
  22582.     aBool
  22583.         ifTrue:[flags _ flags bitOr: VBTrackAmbient]
  22584.         ifFalse:[flags _ flags bitAnd: VBTrackAmbient bitInvert32]! !
  22585.  
  22586. !B3DVertexBuffer methodsFor: 'attributes' stamp: 'ar 2/8/1999 17:37'!
  22587. trackDiffuseColor: aBool
  22588.     aBool
  22589.         ifTrue:[flags _ flags bitOr: VBTrackDiffuse]
  22590.         ifFalse:[flags _ flags bitAnd: VBTrackDiffuse bitInvert32]! !
  22591.  
  22592. !B3DVertexBuffer methodsFor: 'attributes' stamp: 'ar 2/8/1999 17:37'!
  22593. trackEmissionColor: aBool
  22594.     aBool
  22595.         ifTrue:[flags _ flags bitOr: VBTrackEmission]
  22596.         ifFalse:[flags _ flags bitAnd: VBTrackEmission bitInvert32]! !
  22597.  
  22598. !B3DVertexBuffer methodsFor: 'attributes' stamp: 'ar 2/8/1999 17:37'!
  22599. trackSpecularColor: aBool
  22600.     aBool
  22601.         ifTrue:[flags _ flags bitOr: VBTrackSpecular]
  22602.         ifFalse:[flags _ flags bitAnd: VBTrackSpecular bitInvert32]! !
  22603.  
  22604. !B3DVertexBuffer methodsFor: 'attributes'!
  22605. vertex
  22606.     ^current position! !
  22607.  
  22608. !B3DVertexBuffer methodsFor: 'attributes' stamp: 'ar 2/7/1999 04:05'!
  22609. vertex: aVector
  22610.     current position: aVector.
  22611.     self addPrimitiveVertex: current.! !
  22612.  
  22613. !B3DVertexBuffer methodsFor: 'private' stamp: 'ar 2/7/1999 02:31'!
  22614. errorSizeMismatch
  22615.     ^self error:'Vertex size mismatch'! !
  22616.  
  22617. !B3DVertexBuffer methodsFor: 'private' stamp: 'ar 2/7/1999 02:41'!
  22618. growIndexArray: newSize
  22619.     | newIdxArray |
  22620.     newIdxArray _ indexArray species new: newSize.
  22621.     newIdxArray replaceFrom: 1 to: indexArray size with: indexArray startingAt: 1.
  22622.     indexArray _ newIdxArray.! !
  22623.  
  22624. !B3DVertexBuffer methodsFor: 'private' stamp: 'ar 4/14/1999 02:35'!
  22625. growVertexArray: newSize
  22626.     | newVtxArray |
  22627.     newVtxArray _ vertexArray species new: newSize.
  22628.     newVtxArray privateReplaceFrom: 1 to: vertexArray basicSize with: vertexArray startingAt: 1.
  22629.     vertexArray _ newVtxArray.! !
  22630.  
  22631. !B3DVertexBuffer methodsFor: 'testing' stamp: 'ar 2/8/1999 17:32'!
  22632. hasVertexNormals
  22633.     ^flags anyMask: VBVtxHasNormals! !
  22634.  
  22635. !B3DVertexBuffer methodsFor: 'testing' stamp: 'ar 2/8/1999 17:32'!
  22636. hasVertexTexCoords
  22637.     ^flags anyMask: VBVtxHasTexCoords! !
  22638.  
  22639. !B3DVertexBuffer methodsFor: 'testing' stamp: 'ar 2/8/1999 17:32'!
  22640. trackAmbientColor
  22641.     "Return true if the vertex colors override the ambient part of material entries."
  22642.     ^flags anyMask: VBTrackAmbient! !
  22643.  
  22644. !B3DVertexBuffer methodsFor: 'testing' stamp: 'ar 2/8/1999 17:32'!
  22645. trackDiffuseColor
  22646.     "Return true if the vertex colors override the diffuse part of material entries."
  22647.     ^flags anyMask: VBTrackDiffuse! !
  22648.  
  22649. !B3DVertexBuffer methodsFor: 'testing' stamp: 'ar 2/8/1999 17:32'!
  22650. trackEmissionColor
  22651.     "Return true if the vertex colors override the emissive part of material entries."
  22652.     ^flags anyMask: VBTrackEmission! !
  22653.  
  22654. !B3DVertexBuffer methodsFor: 'testing' stamp: 'ar 2/8/1999 17:33'!
  22655. trackSpecularColor
  22656.     "Return true if the vertex colors override the specular part of material entries."
  22657.     ^flags anyMask: VBTrackSpecular! !
  22658.  
  22659. !B3DVertexBuffer methodsFor: 'testing' stamp: 'ar 2/8/1999 17:35'!
  22660. twoSidedLighting
  22661.     "Return true if we shade front and back facing polygons differently"
  22662.     ^flags anyMask: VBTwoSidedLighting! !
  22663.  
  22664. !B3DVertexBuffer methodsFor: 'testing' stamp: 'ar 2/8/1999 17:35'!
  22665. useLocalViewer
  22666.     ^flags anyMask: VBUseLocalViewer! !
  22667.  
  22668. !B3DVertexBuffer methodsFor: 'protected' stamp: 'ar 4/19/1999 16:16'!
  22669. addClipIndex: index
  22670.     "Add a primitive index to the list of indexes."
  22671.     indexCount >= indexArray size 
  22672.         ifTrue:[self growIndexArray: indexCount + (indexCount // 4) + 10].
  22673.     indexArray at: (indexCount _ indexCount + 1) put: index.! !
  22674.  
  22675. !B3DVertexBuffer methodsFor: 'protected' stamp: 'ar 4/19/1999 16:16'!
  22676. addClipVertex: pVtx
  22677.     "Add a primitive vertex to the list of vertices processed.
  22678.     Return the index of the vertex."
  22679.     vertexCount >= vertexArray size 
  22680.         ifTrue:[self growVertexArray: vertexCount + (vertexCount // 4) + 10].
  22681.     vertexArray at: (vertexCount _ vertexCount + 1) put: pVtx.
  22682.     ^vertexCount! !
  22683.  
  22684. !B3DVertexBuffer methodsFor: 'protected' stamp: 'ar 2/7/1999 23:13'!
  22685. addPrimitiveIndex: index
  22686.     "Add a primitive index to the list of indexes."
  22687.     indexCount >= indexArray size 
  22688.         ifTrue:[self growIndexArray: indexCount * 3 // 2 + 100].
  22689.     indexArray at: (indexCount _ indexCount + 1) put: index.! !
  22690.  
  22691. !B3DVertexBuffer methodsFor: 'protected' stamp: 'ar 2/7/1999 04:02'!
  22692. addPrimitiveVertex: pVtx
  22693.     "Add a primitive vertex to the list of vertices processed.
  22694.     Return the index of the vertex."
  22695.     vertexCount >= vertexArray size 
  22696.         ifTrue:[self growVertexArray: vertexCount * 3 // 2 + 100].
  22697.     vertexArray at: (vertexCount _ vertexCount + 1) put: pVtx.
  22698.     ^vertexCount! !
  22699.  
  22700. !B3DVertexBuffer methodsFor: 'protected' stamp: 'ar 2/7/1999 23:16'!
  22701. growForClip
  22702.     vertexCount*2+100 > vertexArray size ifTrue:[self growVertexArray: vertexCount*2+100].
  22703.     indexCount*2+100 > indexArray size ifTrue:[self growIndexArray: indexCount*2+100].! !
  22704.  
  22705. !B3DVertexBuffer methodsFor: 'protected' stamp: 'ar 2/7/1999 16:07'!
  22706. primitiveColorAt: index
  22707.     ^(vertexArray at: index) color! !
  22708.  
  22709. !B3DVertexBuffer methodsFor: 'protected' stamp: 'ar 2/7/1999 04:04'!
  22710. primitiveIndexAt: index
  22711.     ^indexArray at: index! !
  22712.  
  22713. !B3DVertexBuffer methodsFor: 'protected' stamp: 'ar 2/7/1999 04:05'!
  22714. primitiveIndexAt: index put: value
  22715.     ^indexArray at: index put: value! !
  22716.  
  22717. !B3DVertexBuffer methodsFor: 'protected' stamp: 'ar 2/7/1999 04:04'!
  22718. primitiveVertexAt: index
  22719.     ^vertexArray at: index! !
  22720.  
  22721. !B3DVertexBuffer methodsFor: 'protected' stamp: 'ar 2/7/1999 04:04'!
  22722. primitiveVertexAt: index put: aPrimitiveVertex
  22723.     ^vertexArray at: index put: aPrimitiveVertex! !
  22724.  
  22725. !B3DVertexBuffer methodsFor: 'primitives' stamp: 'ar 4/5/1999 11:48'!
  22726. primLoadIndexArrayInto: dstArray startingAt: dstStart from: idxArray count: count max: maxValue offset: vtxOffset
  22727.     "Primitive. Load the given index array into the receiver.
  22728.     NOTE: dstStart is a zero-based index."
  22729.     | idx |
  22730.     <primitive:'b3dLoadIndexArray' module:'Squeak3D'>
  22731.     "self flag: #b3dDebug.    self primitiveFailed."
  22732.     1 to: count do:[:i|
  22733.         idx _ idxArray basicAt: i.
  22734.         (idx < 1 or:[idx > maxValue]) ifTrue:[^self error:'Index out of range'].
  22735.         dstArray at: dstStart + i put: idx + vtxOffset.
  22736.     ].
  22737.     ^count! !
  22738.  
  22739. !B3DVertexBuffer methodsFor: 'primitives' stamp: 'ar 4/5/1999 11:48'!
  22740. primLoadVB: dstArray startingAt: dstStart vertices: vertices normals: normals colors: colors texCoords: texCoords count: count default: defaultValues
  22741.     | hasNormals hasColors hasTexCoords pVtx defaultNormal defaultColor defaultTexCoords |
  22742.     <primitive:'b3dLoadVertexBuffer' module:'Squeak3D'>
  22743.     "self flag: #b3dDebug.    self primitiveFailed."
  22744.     defaultNormal _ defaultValues normal.
  22745.     defaultColor _ defaultValues color.
  22746.     defaultTexCoords _ defaultValues texCoords.
  22747.     hasNormals _ normals notNil.
  22748.     hasColors _ colors notNil.
  22749.     hasTexCoords _ texCoords notNil.
  22750.     1 to: count do:[:i|
  22751.         pVtx _ dstArray at: dstStart + i.
  22752.         pVtx position: (vertices at: i).
  22753.         pVtx normal: (hasNormals ifTrue:[normals at: i] ifFalse:[defaultNormal]).
  22754.         pVtx color: (hasColors ifTrue:[colors at: i] ifFalse:[defaultColor]).
  22755.         pVtx texCoords: (hasTexCoords ifTrue:[texCoords at: i] ifFalse:[defaultTexCoords]).
  22756.         dstArray at: dstStart + i put: pVtx.
  22757.     ].
  22758.     ^count! !
  22759.  
  22760. !B3DVertexBuffer class methodsFor: 'instance creation'!
  22761. new
  22762.     ^super new initialize! !
  22763.  
  22764. !B3DVertexBufferPlugin methodsFor: 'primitives' stamp: 'ar 2/14/1999 23:32'!
  22765. b3dLoadIndexArray
  22766.     "Primitive. Load the given index array into the receiver.
  22767.     NOTE: dstStart is a zero-based index."
  22768.     | vtxOffset maxValue count srcArray srcPtr idx dstStart dstArray dstSize dstPtr |
  22769.     self export: true.
  22770.     self inline: false.
  22771.     self var: #dstPtr declareC:'int *dstPtr'.
  22772.     self var: #srcPtr declareC:'int *srcPtr'.
  22773.     "Load the arguments"
  22774.     vtxOffset _ interpreterProxy stackIntegerValue: 0.
  22775.     maxValue _ interpreterProxy stackIntegerValue: 1.
  22776.     count _ interpreterProxy stackIntegerValue: 2.
  22777.     srcArray _ interpreterProxy stackObjectValue: 3.
  22778.     dstStart _ interpreterProxy stackIntegerValue: 4.
  22779.     dstArray _ interpreterProxy stackObjectValue: 5.
  22780.     interpreterProxy failed ifTrue:[^nil]. "Will cover all possible problems above"
  22781.     "Check srcArray"
  22782.     (interpreterProxy isWords: srcArray)
  22783.         ifFalse:[^interpreterProxy primitiveFail].
  22784.     ((interpreterProxy slotSizeOf: srcArray) < count)
  22785.         ifTrue:[^interpreterProxy primitiveFail].
  22786.     srcPtr _ self cCoerce: (interpreterProxy firstIndexableField: srcArray) to:'int*'.
  22787.     "Check dstArray"
  22788.      dstSize _ interpreterProxy slotSizeOf: dstArray.
  22789.     "Check if there is enough room left in dstArray"
  22790.     dstStart + count > dstSize
  22791.         ifTrue:[^interpreterProxy primitiveFail].
  22792.     dstPtr _ self cCoerce: (interpreterProxy firstIndexableField: dstArray) to:'int *'.
  22793.     "Do the actual work"
  22794.     0 to: count-1 do:[:i|
  22795.         idx _ srcPtr at: i.
  22796.         (idx < 1 or:[idx > maxValue]) 
  22797.             ifTrue:[^interpreterProxy primitiveFail].
  22798.         dstPtr at: dstStart + i put: idx + vtxOffset.
  22799.     ].
  22800.     "Clean up the stack"
  22801.     interpreterProxy pop: 7. "Pop args+rcvr"
  22802.     interpreterProxy pushInteger: count.
  22803. ! !
  22804.  
  22805. !B3DVertexBufferPlugin methodsFor: 'primitives' stamp: 'ar 2/17/1999 04:30'!
  22806. b3dLoadVertexBuffer
  22807.     "Primitive. Load the data into the given vertex buffer.
  22808.     NOTE: dstStart is a zero-based index."
  22809.     | defaultVtx defaultNormal defaultTexCoords defaultColor count texPtr colorPtr normalPtr vtxPtr dstStart dstPtr pVtx |
  22810.  
  22811.     self export: true.
  22812.     self inline: false.
  22813.  
  22814.     self var: #defaultVtx declareC:'int *defaultVtx'.
  22815.     self var: #defaultNormal declareC:'int *defaultNormal'.
  22816.     self var: #defaultTexCoords declareC:'int *defaultTexCoords'.
  22817.     self var: #defaultColor declareC:'int *defaultColor'.
  22818.  
  22819.     self var: #texPtr declareC:'int *texPtr'.
  22820.     self var: #colorPtr declareC:'int *colorPtr'.
  22821.     self var: #normalPtr declareC:'int *normalPtr'.
  22822.     self var: #vtxPtr declareC:'int *vtxPtr'.
  22823.     self var: #dstPtr declareC:'int *dstPtr'.
  22824.     self var: #pVtx declareC:'int *pVtx'.
  22825.  
  22826.     defaultVtx _ self stackPrimitiveVertex: 0.
  22827.     count _ interpreterProxy stackIntegerValue: 1.
  22828.     texPtr _ self vbLoadArray: (interpreterProxy stackObjectValue: 2) 
  22829.                 size: 2*count.
  22830.     colorPtr _ self vbLoadArray: (interpreterProxy stackObjectValue: 3) 
  22831.                 size: count.
  22832.     normalPtr _ self vbLoadArray: (interpreterProxy stackObjectValue: 4) 
  22833.                 size: 3*count.
  22834.     vtxPtr _ self vbLoadArray: (interpreterProxy stackObjectValue: 5) 
  22835.                 size: 3*count.
  22836.     dstStart _ interpreterProxy stackIntegerValue: 6.
  22837.     dstPtr _ self stackPrimitiveVertexArray: 7 ofSize: dstStart + count.
  22838.     "Check for all problems above"
  22839.     (dstPtr = nil or:[defaultVtx == nil or:[interpreterProxy failed]]) 
  22840.         ifTrue:[^interpreterProxy primitiveFail].
  22841.  
  22842.     "Install default values"
  22843.     normalPtr = nil
  22844.         ifTrue:[defaultNormal _ defaultVtx + PrimVtxNormal]
  22845.         ifFalse:[defaultNormal _ normalPtr].
  22846.     texPtr = nil
  22847.         ifTrue:[defaultTexCoords _ defaultVtx + PrimVtxTexCoords]
  22848.         ifFalse:[defaultTexCoords _ texPtr].
  22849.     colorPtr = nil
  22850.         ifTrue:[defaultColor _ defaultVtx + PrimVtxColor32]
  22851.         ifFalse:[defaultColor _ colorPtr].
  22852.     "Do the actual stuff"
  22853.     pVtx _ dstPtr + (dstStart * PrimVertexSize).
  22854.     0 to: count-1 do:[:i|
  22855.         pVtx at: PrimVtxPositionX put: (vtxPtr at: 0).
  22856.         pVtx at: PrimVtxPositionY put: (vtxPtr at: 1).
  22857.         pVtx at: PrimVtxPositionZ put: (vtxPtr at: 2).
  22858.         pVtx at: PrimVtxNormalX put: (defaultNormal at: 0).
  22859.         pVtx at: PrimVtxNormalY put: (defaultNormal at: 1).
  22860.         pVtx at: PrimVtxNormalZ put: (defaultNormal at: 2).
  22861.         pVtx at: PrimVtxColor32 put: (defaultColor at: 0).
  22862.         pVtx at: PrimVtxTexCoordU put: (defaultTexCoords at: 0).
  22863.         pVtx at: PrimVtxTexCoordV put: (defaultTexCoords at: 1).
  22864.         "And go to the next vertex"
  22865.         pVtx _ pVtx + PrimVertexSize.
  22866.         vtxPtr _ vtxPtr + 3.
  22867.         normalPtr = nil ifFalse:[defaultNormal _ defaultNormal + 3].
  22868.         colorPtr = nil ifFalse:[defaultColor _ defaultColor + 1].
  22869.         texPtr = nil ifFalse:[defaultTexCoords _ defaultTexCoords + 2].
  22870.     ].
  22871.     "Clean up stack"
  22872.     interpreterProxy pop: 8. "Pop args+rcvr"
  22873.     interpreterProxy pushInteger: count.! !
  22874.  
  22875. !B3DVertexBufferPlugin methodsFor: 'private' stamp: 'ar 4/17/1999 22:29'!
  22876. vbLoadArray: oop size: count
  22877.     "Load the word based array of size count from the given oop"
  22878.     self returnTypeC: 'void*'.
  22879.     self inline: false.
  22880.     oop == nil ifTrue:[interpreterProxy primitiveFail. ^nil].
  22881.     oop == interpreterProxy nilObject ifTrue:[^nil].
  22882.     (interpreterProxy isWords: oop) 
  22883.         ifFalse:[interpreterProxy primitiveFail. ^nil].
  22884.     (interpreterProxy slotSizeOf: oop) = count
  22885.         ifFalse:[interpreterProxy primitiveFail. ^nil].
  22886.     ^interpreterProxy firstIndexableField: oop! !
  22887.  
  22888. I provide clipping capabilities for rasterizers needing explicit clipping.!
  22889. !B3DVertexClipper methodsFor: 'processing' stamp: 'ar 4/17/1999 23:06'!
  22890. processIndexedLines: vb
  22891.     "Process an indexed line set"
  22892.     ^self error:'Lines are not yet implemented'! !
  22893.  
  22894. !B3DVertexClipper methodsFor: 'processing' stamp: 'ar 9/17/1999 20:08'!
  22895. processIndexedQuads: vb
  22896.     "Clip an indexed quad set"
  22897.     | vtxArray idxArray tempVB idx1 idx2 idx3 maxVtx maxIdx index lastIndex clipFlags vtx returnValue |
  22898.     self flag: #b3dPrimitive.
  22899.     returnValue _ false. "Assume we don't see nothing"
  22900.     tempVB _ B3DVertexBuffer new.
  22901.     vtxArray _ vb vertexArray.
  22902.     idxArray _ vb indexArray.
  22903.     maxVtx _ vb indexCount.
  22904.     maxIdx _ vb indexCount.
  22905.     lastIndex _ -3. "Hack the lastIndex ;-)"
  22906.     [index _ self primNextClippedQuadAfter: lastIndex + 4
  22907.                     vertices: vtxArray count: maxVtx
  22908.                     indexes: idxArray count: maxIdx.
  22909.     index = 0] whileFalse:[
  22910.         "Need a partial clip here, storing the triangulated polygon at the end"
  22911.         tempVB reset.
  22912.         clipFlags _ InAllMask + OutAllMask.
  22913.         "Copy the poly into tempVB"
  22914.         0 to: 3 do:[:i|
  22915.             vtx _ vtxArray at: (idxArray at: index+i).
  22916.             idxArray at: index+i put: 0.
  22917.             tempVB addClipVertex: vtx.
  22918.             clipFlags _ clipFlags bitAnd: vtx clipFlags].
  22919.         tempVB clipFlags: clipFlags.
  22920.         self processPolygon: tempVB.
  22921.         tempVB vertexCount > 2 ifTrue:[
  22922.             returnValue _ nil. "We see some parts and not others"
  22923.             idx1 _ vb addClipVertex: (tempVB vertexArray at: 1).
  22924.             3 to: tempVB vertexCount do:[:j|
  22925.                 idx2 _ vb addClipVertex: (tempVB vertexArray at: j-1).
  22926.                 idx3 _ vb addClipVertex: (tempVB vertexArray at: j).
  22927.                 vb addClipIndex: idx1.
  22928.                 vb addClipIndex: idx2.
  22929.                 vb addClipIndex: idx3.
  22930.                 vb addClipIndex: idx3.
  22931.             ].
  22932.         ].
  22933.         lastIndex _ index.
  22934.     ].
  22935.     ^returnValue! !
  22936.  
  22937. !B3DVertexClipper methodsFor: 'processing' stamp: 'ar 9/17/1999 20:08'!
  22938. processIndexedTriangles: vb
  22939.     "Clip an indexed triangle set"
  22940.     | vtxArray idxArray tempVB idx1 idx2 idx3 maxVtx maxIdx index lastIndex clipFlags vtx returnValue |
  22941.     self flag: #b3dPrimitive.
  22942.     returnValue _ false. "Assume we don't see nothing"
  22943.     tempVB _ B3DVertexBuffer new.
  22944.     vtxArray _ vb vertexArray.
  22945.     idxArray _ vb indexArray.
  22946.     maxVtx _ vb indexCount.
  22947.     maxIdx _ vb indexCount.
  22948.     lastIndex _ -2. "Hack the lastIndex ;-)"
  22949.     [index _ self primNextClippedTriangleAfter: lastIndex + 3
  22950.                     vertices: vtxArray count: maxVtx
  22951.                     indexes: idxArray count: maxIdx.
  22952.     index = 0] whileFalse:[
  22953.         "Need a partial clip here, storing the triangulated polygon at the end"
  22954.         tempVB reset.
  22955.         clipFlags _ InAllMask + OutAllMask.
  22956.         "Copy the poly into tempVB"
  22957.         0 to: 2 do:[:i|
  22958.             vtx _ vtxArray at: (idxArray at: index+i).
  22959.             idxArray at: index+i put: 0.
  22960.             tempVB addClipVertex: vtx.
  22961.             clipFlags _ clipFlags bitAnd: vtx clipFlags].
  22962.         tempVB clipFlags: clipFlags.
  22963.         self processPolygon: tempVB.
  22964.         tempVB vertexCount > 2 ifTrue:[
  22965.             returnValue _ nil. "We see some parts and not others"
  22966.             idx1 _ vb addClipVertex: (tempVB vertexArray at: 1).
  22967.             3 to: tempVB vertexCount do:[:j|
  22968.                 idx2 _ vb addClipVertex: (tempVB vertexArray at: j-1).
  22969.                 idx3 _ vb addClipVertex: (tempVB vertexArray at: j).
  22970.                 vb addClipIndex: idx1.
  22971.                 vb addClipIndex: idx2.
  22972.                 vb addClipIndex: idx3.
  22973.             ].
  22974.         ].
  22975.         lastIndex _ index.
  22976.     ].
  22977.     ^returnValue! !
  22978.  
  22979. !B3DVertexClipper methodsFor: 'processing' stamp: 'ar 4/17/1999 23:06'!
  22980. processLineLoop: vertexBuffer
  22981.     "Process a closed line defined by the vertex buffer"
  22982.     ^self error:'Lines are not yet implemented'! !
  22983.  
  22984. !B3DVertexClipper methodsFor: 'processing' stamp: 'ar 4/17/1999 23:06'!
  22985. processLines: vertexBuffer
  22986.     "Process a series of lines defined by each two points the vertex buffer"
  22987.     ^self error:'Lines are not yet implemented'! !
  22988.  
  22989. !B3DVertexClipper methodsFor: 'processing' stamp: 'ar 4/17/1999 23:06'!
  22990. processPoints: vertexBuffer
  22991.     "Process a series of points defined by the vertex buffer"
  22992.     ^self error:'Points are not yet implemented'! !
  22993.  
  22994. !B3DVertexClipper methodsFor: 'processing' stamp: 'ar 9/17/1999 20:10'!
  22995. processPolygon: vb
  22996.     "Process a polygon from the vertex buffer that requires partial clipping"
  22997.     | outMask vtxArray tempVtxArray count |
  22998.     outMask := vb clipFlags bitAnd: OutAllMask.
  22999.     vtxArray _ vb vertexArray.
  23000.     tempVtxArray _ vtxArray clone.
  23001.     "Note: tempVtxArray has the SAME contents as vtxArray since the data is stored inplace.
  23002.     Thus we can decide from which buffer to start the clipping operation later on."
  23003.     count _ self clipPolygon: vtxArray count: vb vertexCount with: tempVtxArray mask: outMask.
  23004.     vb vertexCount: count.
  23005.     count < 3 ifTrue:[^false].
  23006.     ^nil! !
  23007.  
  23008. !B3DVertexClipper methodsFor: 'processing' stamp: 'ar 9/17/1999 20:05'!
  23009. processVertexBuffer: vb
  23010.     "Clip the elements in the vertex buffer. Return true if all vertices are inside.
  23011.     Return false if all vertices are outside. If partial clipping occurs, return nil."
  23012.     | fullMask |
  23013.     fullMask _ self determineClipFlags: vb vertexArray count: vb vertexCount.
  23014.     vb clipFlags: fullMask.
  23015.     "Check if all vertices are inside, so no clipping is necessary"
  23016.     (fullMask allMask: InAllMask) ifTrue:[^true].
  23017.     "Check if all vertices are outside, so we can get rid of the entire buffer"
  23018.     (fullMask anyMask: OutAllMask) ifTrue:[
  23019.         "Reset the number of vertices in the vertex buffer to zero to indicate all outside"
  23020.         vb reset.
  23021.         ^false].
  23022.     "Must clip individual items depending on the primitive type"
  23023.     vb growForClip. "Make sure we have enough space during primitive operation"
  23024.     ^super processVertexBuffer: vb.! !
  23025.  
  23026. !B3DVertexClipper methodsFor: 'clip flags' stamp: 'ar 2/16/1999 19:20'!
  23027. clipFlagsX: x y: y z: z w: w
  23028.     "Determine the clip flags for the given vector.
  23029.     The clip flags are a combination of inside and outside flags that can be used to easily reject an entire buffer if it is completely inside or outside and can also be used to detect the most commen cases in clipping (e.g., intersection with one boundary only)."
  23030.     | w2 flags |
  23031.     w2 _ w negated.
  23032.     flags _ 0.
  23033.     flags _ flags bitOr:(x >= w2 ifTrue:[InLeftBit] ifFalse:[OutLeftBit]).
  23034.     flags _ flags bitOr:(x <= w ifTrue:[InRightBit] ifFalse:[OutRightBit]).
  23035.     flags _ flags bitOr:(y >= w2 ifTrue:[InBottomBit] ifFalse:[OutBottomBit]).
  23036.     flags _ flags bitOr:(y <= w ifTrue:[InTopBit] ifFalse:[OutTopBit]).
  23037.     flags _ flags bitOr:(z >= w2 ifTrue:[InFrontBit] ifFalse:[OutFrontBit]).
  23038.     flags _ flags bitOr:(z <= w ifTrue:[InBackBit] ifFalse:[OutBackBit]).
  23039.     ^flags! !
  23040.  
  23041. !B3DVertexClipper methodsFor: 'clip flags' stamp: 'ar 2/16/1999 19:20'!
  23042. determineClipFlags: vtxArray count: vtxCount
  23043.     "Determine the clip flags for all the vertices in the vertex array"
  23044.     | fullMask flags |
  23045.     self flag: #b3dPrimitive.
  23046.     fullMask _ InAllMask + OutAllMask.
  23047.     vtxArray upTo: vtxCount do:[:vtx|
  23048.         flags _ (self clipFlagsX: vtx rasterPosX 
  23049.                             y: vtx rasterPosY 
  23050.                             z: vtx rasterPosZ 
  23051.                             w: vtx rasterPosW).
  23052.         vtx clipFlags: flags.
  23053.         fullMask _ fullMask bitAnd: flags.
  23054.     ].
  23055.     ^fullMask! !
  23056.  
  23057. !B3DVertexClipper methodsFor: 'clipping polygons' stamp: 'ar 2/16/1999 19:21'!
  23058. clipPolygon: vtxArray count: vtxCount with: tempVtxArray mask: outMask
  23059.     "Clip the polygon defined by vtxCount vertices in vtxArray. tempVtxArray is a temporary storage area used for copying the vertices back and forth during clipping operation. outMask is the full clip mask of the vertex buffer, allowing some optimizations of the clipping code.
  23060.     NOTE: It is significant here that the contents of vtxArray and tempVtxArray are equal."
  23061.     | count |
  23062.     self flag: #b3dPrimitive.
  23063.     "Check if the polygon is outside one boundary only.
  23064.     If so, just do this single clipping operation avoiding multiple enumeration."
  23065.     outMask = OutLeftBit 
  23066.         ifTrue:[^self clipPolygonLeftFrom: tempVtxArray to: vtxArray count: vtxCount].
  23067.     outMask = OutRightBit 
  23068.         ifTrue:[^self clipPolygonRightFrom: tempVtxArray to: vtxArray count: vtxCount].
  23069.     outMask = OutTopBit 
  23070.         ifTrue:[^self clipPolygonTopFrom: tempVtxArray to: vtxArray count: vtxCount].
  23071.     outMask = OutBottomBit 
  23072.         ifTrue:[^self clipPolygonBottomFrom: tempVtxArray to: vtxArray count: vtxCount].
  23073.     outMask = OutFrontBit 
  23074.         ifTrue:[^self clipPolygonFrontFrom: tempVtxArray to: vtxArray count: vtxCount].
  23075.     outMask = OutBackBit 
  23076.         ifTrue:[^self clipPolygonBackFrom: tempVtxArray to: vtxArray count: vtxCount].
  23077.     "Just do each of the clipping operations"
  23078.     count _ vtxCount.
  23079.     count _ self clipPolygonLeftFrom: vtxArray to: tempVtxArray count: count.
  23080.     count = 0 ifTrue:[^0].
  23081.     count _ self clipPolygonRightFrom: tempVtxArray to: vtxArray count: count.
  23082.     count = 0 ifTrue:[^0].
  23083.     count _ self clipPolygonTopFrom: vtxArray to: tempVtxArray count: count.
  23084.     count = 0 ifTrue:[^0].
  23085.     count _ self clipPolygonBottomFrom: tempVtxArray to: vtxArray count: count.
  23086.     count = 0 ifTrue:[^0].
  23087.     count _ self clipPolygonFrontFrom: vtxArray to: tempVtxArray count: count.
  23088.     count = 0 ifTrue:[^0].
  23089.     count _ self clipPolygonBackFrom: tempVtxArray to: vtxArray count: count.
  23090.     ^count! !
  23091.  
  23092. !B3DVertexClipper methodsFor: 'clipping polygons' stamp: 'ar 2/16/1999 19:21'!
  23093. clipPolygonBackFrom: buf1 to: buf2 count: n
  23094.     | last next t outIndex inLast inNext outVtx |
  23095.     outIndex _ 0.
  23096.     last _ buf1 at: n.
  23097.     inLast _ last clipFlags anyMask: InBackBit.
  23098.     1 to: n do:[:i|
  23099.         next _ buf1 at: i.
  23100.         inNext _ next clipFlags anyMask: InBackBit.
  23101.         inLast = inNext ifFalse:["Passes clip boundary"
  23102.             t _ self backClipValueFrom: last to: next.
  23103.             outVtx _ self interpolateFrom: last to: next at: t.
  23104.             buf2 at: (outIndex _ outIndex+1) put: outVtx].
  23105.         inNext ifTrue:[buf2 at: (outIndex _ outIndex+1) put: next].
  23106.         last _ next.
  23107.         inLast _ inNext.
  23108.     ].
  23109.     ^outIndex! !
  23110.  
  23111. !B3DVertexClipper methodsFor: 'clipping polygons' stamp: 'ar 2/16/1999 19:21'!
  23112. clipPolygonBottomFrom: buf1 to: buf2 count: n
  23113.     | last next t outIndex inLast inNext outVtx |
  23114.     outIndex _ 0.
  23115.     last _ buf1 at: n.
  23116.     inLast _ last clipFlags anyMask: InBottomBit.
  23117.     1 to: n do:[:i|
  23118.         next _ buf1 at: i.
  23119.         inNext _ next clipFlags anyMask: InBottomBit.
  23120.         inLast = inNext ifFalse:["Passes clip boundary"
  23121.             t _ self bottomClipValueFrom: last to: next.
  23122.             outVtx _ self interpolateFrom: last to: next at: t.
  23123.             buf2 at: (outIndex _ outIndex+1) put: outVtx].
  23124.         inNext ifTrue:[buf2 at: (outIndex _ outIndex+1) put: next].
  23125.         last _ next.
  23126.         inLast _ inNext.
  23127.     ].
  23128.     ^outIndex! !
  23129.  
  23130. !B3DVertexClipper methodsFor: 'clipping polygons' stamp: 'ar 2/16/1999 19:21'!
  23131. clipPolygonFrontFrom: buf1 to: buf2 count: n
  23132.     | last next t outIndex inLast inNext outVtx |
  23133.     outIndex _ 0.
  23134.     last _ buf1 at: n.
  23135.     inLast _ last clipFlags anyMask: InFrontBit.
  23136.     1 to: n do:[:i|
  23137.         next _ buf1 at: i.
  23138.         inNext _ next clipFlags anyMask: InFrontBit.
  23139.         inLast = inNext ifFalse:["Passes clip boundary"
  23140.             t _ self frontClipValueFrom: last to: next.
  23141.             outVtx _ self interpolateFrom: last to: next at: t.
  23142.             buf2 at: (outIndex _ outIndex+1) put: outVtx].
  23143.         inNext ifTrue:[buf2 at: (outIndex _ outIndex+1) put: next].
  23144.         last _ next.
  23145.         inLast _ inNext.
  23146.     ].
  23147.     ^outIndex! !
  23148.  
  23149. !B3DVertexClipper methodsFor: 'clipping polygons' stamp: 'ar 4/16/1999 06:01'!
  23150. clipPolygonLeftFrom: buf1 to: buf2 count: n
  23151.     | last next t outIndex inLast inNext outVtx |
  23152.     outIndex _ 0.
  23153.     last _ buf1 at: n.
  23154.     inLast _ last clipFlags anyMask: InLeftBit.
  23155.     1 to: n do:[:i|
  23156.         next _ buf1 at: i.
  23157.         inNext _ next clipFlags anyMask: InLeftBit.
  23158.         inLast = inNext ifFalse:["Passes clip boundary"
  23159.             t _ self leftClipValueFrom: last to: next.
  23160.             outVtx _ self interpolateFrom: last to: next at: t.
  23161.             buf2 at: (outIndex _ outIndex+1) put: outVtx].
  23162.         inNext ifTrue:[buf2 at: (outIndex _ outIndex+1) put: next].
  23163.         last _ next.
  23164.         inLast _ inNext.
  23165.     ].
  23166.     ^outIndex! !
  23167.  
  23168. !B3DVertexClipper methodsFor: 'clipping polygons' stamp: 'ar 2/16/1999 19:21'!
  23169. clipPolygonRightFrom: buf1 to: buf2 count: n
  23170.     | last next t outIndex inLast inNext outVtx |
  23171.     outIndex _ 0.
  23172.     last _ buf1 at: n.
  23173.     inLast _ last clipFlags anyMask: InRightBit.
  23174.     1 to: n do:[:i|
  23175.         next _ buf1 at: i.
  23176.         inNext _ next clipFlags anyMask: InRightBit.
  23177.         inLast = inNext ifFalse:["Passes clip boundary"
  23178.             t _ self rightClipValueFrom: last to: next.
  23179.             outVtx _ self interpolateFrom: last to: next at: t.
  23180.             buf2 at: (outIndex _ outIndex+1) put: outVtx].
  23181.         inNext ifTrue:[buf2 at: (outIndex _ outIndex+1) put: next].
  23182.         last _ next.
  23183.         inLast _ inNext.
  23184.     ].
  23185.     ^outIndex! !
  23186.  
  23187. !B3DVertexClipper methodsFor: 'clipping polygons' stamp: 'ar 2/16/1999 19:21'!
  23188. clipPolygonTopFrom: buf1 to: buf2 count: n
  23189.     | last next t outIndex inLast inNext outVtx |
  23190.     outIndex _ 0.
  23191.     last _ buf1 at: n.
  23192.     inLast _ last clipFlags anyMask: InTopBit.
  23193.     1 to: n do:[:i|
  23194.         next _ buf1 at: i.
  23195.         inNext _ next clipFlags anyMask: InTopBit.
  23196.         inLast = inNext ifFalse:["Passes clip boundary"
  23197.             t _ self topClipValueFrom: last to: next.
  23198.             outVtx _ self interpolateFrom: last to: next at: t.
  23199.             buf2 at: (outIndex _ outIndex+1) put: outVtx].
  23200.         inNext ifTrue:[buf2 at: (outIndex _ outIndex+1) put: next].
  23201.         last _ next.
  23202.         inLast _ inNext.
  23203.     ].
  23204.     ^outIndex! !
  23205.  
  23206. !B3DVertexClipper methodsFor: 'clipping utilitites' stamp: 'ar 2/16/1999 19:21'!
  23207. backClipValueFrom: last to: next
  23208.     ^(last rasterPosZ - last rasterPosW) /
  23209.         ((next rasterPosW - last rasterPosW) - (next rasterPosZ - last rasterPosZ)).! !
  23210.  
  23211. !B3DVertexClipper methodsFor: 'clipping utilitites' stamp: 'ar 2/16/1999 19:21'!
  23212. bottomClipValueFrom: last to: next
  23213.     ^(last rasterPosY + last rasterPosW) negated /
  23214.         ((next rasterPosW - last rasterPosW) + (next rasterPosY - last rasterPosY)).! !
  23215.  
  23216. !B3DVertexClipper methodsFor: 'clipping utilitites' stamp: 'ar 2/16/1999 19:21'!
  23217. frontClipValueFrom: last to: next
  23218.     ^(last rasterPosZ + last rasterPosW) negated /
  23219.         ((next rasterPosW - last rasterPosW) + (next rasterPosZ - last rasterPosZ)).! !
  23220.  
  23221. !B3DVertexClipper methodsFor: 'clipping utilitites' stamp: 'ar 4/16/1999 06:43'!
  23222. interpolateFrom: last to: next at: t
  23223.     "Interpolate the primitive vertices last/next at the parameter t"
  23224.     | out |
  23225.     out _ next clone.
  23226.     "Interpolate raster position"
  23227.     out rasterPos: ((next rasterPos - last rasterPos) * t) + last rasterPos.
  23228.     out clipFlags: (self clipFlagsX: out rasterPosX y: out rasterPosY z: out rasterPosZ w: out rasterPosW).
  23229.     "Interpolate color"
  23230.     out b3dColor: ((next b3dColor - last b3dColor) * t) + last b3dColor.
  23231.     "Interpolate texture coordinates"
  23232.     out texCoords: ((next texCoords - last texCoords) * t) + last texCoords.
  23233.     ^out! !
  23234.  
  23235. !B3DVertexClipper methodsFor: 'clipping utilitites' stamp: 'ar 2/16/1999 19:21'!
  23236. leftClipValueFrom: last to: next
  23237.     ^(last rasterPosX + last rasterPosW) negated /
  23238.         ((next rasterPosW - last rasterPosW) + (next rasterPosX - last rasterPosX)).! !
  23239.  
  23240. !B3DVertexClipper methodsFor: 'clipping utilitites' stamp: 'ar 2/16/1999 19:21'!
  23241. rightClipValueFrom: last to: next
  23242.     ^(last rasterPosX - last rasterPosW) /
  23243.         ((next rasterPosW - last rasterPosW) - (next rasterPosX - last rasterPosX)).! !
  23244.  
  23245. !B3DVertexClipper methodsFor: 'clipping utilitites' stamp: 'ar 2/16/1999 19:21'!
  23246. topClipValueFrom: last to: next
  23247.     ^(last rasterPosY - last rasterPosW) /
  23248.         ((next rasterPosW - last rasterPosW) - (next rasterPosY - last rasterPosY)).! !
  23249.  
  23250. !B3DVertexClipper methodsFor: 'private' stamp: 'ar 2/16/1999 19:21'!
  23251. primNextClippedQuadAfter: firstIndex vertices: vtxArray count: vtxCount indexes: idxArray count: idxCount
  23252.     "Find the next partially clipped quad from the vertex buffer and return its index.
  23253.     If there are no more partially clipped quads return zero."
  23254.     | quadMask |
  23255.     self flag: #b3dPrimitive.
  23256.     firstIndex to: idxCount by: 4 do:[:i|
  23257.         quadMask _
  23258.             ((vtxArray at: (idxArray at: i)) clipFlags bitAnd:
  23259.                 (vtxArray at: (idxArray at: i+1)) clipFlags) bitAnd:
  23260.                     ((vtxArray at: (idxArray at: i+2)) clipFlags bitAnd:
  23261.                         (vtxArray at: (idxArray at: i+3)) clipFlags).
  23262.         "Check if quad is completely inside"
  23263.         (quadMask allMask: InAllMask) ifFalse:[
  23264.             "Quad is not completely inside -> needs clipping."
  23265.             (quadMask anyMask: OutAllMask) ifTrue:[
  23266.                 "quad is completely outside. Store all zeros"
  23267.                 idxArray at: i put: 0.
  23268.                 idxArray at: i+1 put: 0.
  23269.                 idxArray at: i+2 put: 0.
  23270.                 idxArray at: i+3 put: 0.
  23271.             ] ifFalse:[
  23272.                 "quad must be partially clipped."
  23273.                 ^i
  23274.             ].
  23275.         ].
  23276.     ].
  23277.     ^0 "No more entries"! !
  23278.  
  23279. !B3DVertexClipper methodsFor: 'private' stamp: 'ar 2/16/1999 19:22'!
  23280. primNextClippedTriangleAfter: firstIndex vertices: vtxArray count: vtxCount indexes: idxArray count: idxCount
  23281.     "Find the next partially clipped triangle from the vertex buffer and return its index.
  23282.     If there are no more partially clipped triangles return zero."
  23283.     | triMask |
  23284.     self flag: #b3dPrimitive.
  23285.     firstIndex to: idxCount by: 3 do:[:i|
  23286.         triMask _
  23287.             ((vtxArray at: (idxArray at: i)) clipFlags bitAnd:
  23288.                 (vtxArray at: (idxArray at: i+1)) clipFlags) bitAnd:
  23289.                     (vtxArray at: (idxArray at: i+2)) clipFlags.
  23290.         "Check if tri is completely inside"
  23291.         (triMask allMask: InAllMask) ifFalse:[
  23292.             "Tri is not completely inside -> needs clipping."
  23293.             (triMask anyMask: OutAllMask) ifTrue:[
  23294.                 "tri is completely outside. Store all zeros"
  23295.                 idxArray at: i put: 0.
  23296.                 idxArray at: i+1 put: 0.
  23297.                 idxArray at: i+2 put: 0.
  23298.             ] ifFalse:[
  23299.                 "tri must be partially clipped."
  23300.                 ^i
  23301.             ].
  23302.         ].
  23303.     ].
  23304.     ^0 "No more entries"! !
  23305.  
  23306. !B3DVertexClipper class methodsFor: 'class initialization' stamp: 'ar 2/13/1999 20:31'!
  23307. initialize
  23308.     "B3DClipper initialize"
  23309.     "InLeftBit _ 16r01.    OutLeftBit _ 16r02.
  23310.     InRightBit _ 16r04.    OutRightBit _ 16r08.
  23311.     InTopBit _ 16r10.        OutTopBit _ 16r20.
  23312.     InBottomBit _ 16r40.    OutBottomBit _ 16r80.
  23313.     InFrontBit _ 16r100.    OutFrontBit _ 16r200.
  23314.     InBackBit _ 16r400.    OutBackBit _ 16r800.
  23315.  
  23316.     InAllMask  _ 16r555. 1365
  23317.     OutAllMask  _ 16rAAA 2730."! !
  23318.  
  23319. !B3DVertexClipper class methodsFor: 'testing' stamp: 'ar 2/14/1999 01:40'!
  23320. isAvailable
  23321.     "Return true if this part of the engine is available"
  23322.     ^true! !
  23323.  
  23324. I am the superclass for all rasterizers in the Balloon 3D engine. Rasterizers perform the final pixel generation of the primitives and are the most time-critical part of the engine. Rasterizers keep a viewport, defining the destination rectangle and a dirtyRect, defining the actual affected 2D region of the rasterization process.
  23325.  
  23326. Instance variables:
  23327.     viewport    <B3DViewport>    the destination rectangle
  23328.     dirtyRect    <Rectangle>        the affected region of all rasterization operations performed!
  23329. !B3DVertexRasterizer methodsFor: 'initialize' stamp: 'ar 2/16/1999 04:30'!
  23330. finish
  23331.     "Force everything on the output device"! !
  23332.  
  23333. !B3DVertexRasterizer methodsFor: 'initialize' stamp: 'ar 5/26/2000 15:29'!
  23334. flush
  23335.     "Flush pending operations."! !
  23336.  
  23337. !B3DVertexRasterizer methodsFor: 'initialize' stamp: 'ar 2/16/1999 03:15'!
  23338. initialize
  23339.     super initialize.
  23340.     textureStack _ OrderedCollection new.! !
  23341.  
  23342. !B3DVertexRasterizer methodsFor: 'initialize' stamp: 'ar 4/10/1999 22:53'!
  23343. reset
  23344.     super reset.
  23345.     textureStack _ OrderedCollection new.! !
  23346.  
  23347. !B3DVertexRasterizer methodsFor: 'initialize' stamp: 'ar 5/26/2000 15:12'!
  23348. target: aForm
  23349.     "Set the target for rendering operations"
  23350.     target _ aForm! !
  23351.  
  23352. !B3DVertexRasterizer methodsFor: 'accessing' stamp: 'ar 5/26/2000 15:18'!
  23353. clipRect
  23354.     "Return the current clipping rectangle"
  23355.     ^clipRect! !
  23356.  
  23357. !B3DVertexRasterizer methodsFor: 'accessing' stamp: 'ar 5/26/2000 15:18'!
  23358. clipRect: aRectangle
  23359.     "Install a clipping rectangle if necessary"
  23360.     clipRect _ aRectangle! !
  23361.  
  23362. !B3DVertexRasterizer methodsFor: 'accessing' stamp: 'ar 2/7/1999 03:38'!
  23363. dirtyRect
  23364.     "If the dirtyRect is not known (e.g., not implemented by a particular rasterizer) return the full viewport"
  23365.     ^dirtyRect ifNil:[viewport]! !
  23366.  
  23367. !B3DVertexRasterizer methodsFor: 'accessing' stamp: 'ar 2/7/1999 03:35'!
  23368. dirtyRect: aRectangle
  23369.     dirtyRect _ aRectangle! !
  23370.  
  23371. !B3DVertexRasterizer methodsFor: 'accessing' stamp: 'ar 2/16/1999 03:16'!
  23372. popTexture
  23373.     texture _ textureStack removeLast.! !
  23374.  
  23375. !B3DVertexRasterizer methodsFor: 'accessing' stamp: 'ar 2/16/1999 03:15'!
  23376. pushTexture
  23377.     textureStack addLast: texture! !
  23378.  
  23379. !B3DVertexRasterizer methodsFor: 'accessing' stamp: 'ar 2/16/1999 03:15'!
  23380. texture
  23381.     ^texture! !
  23382.  
  23383. !B3DVertexRasterizer methodsFor: 'accessing' stamp: 'ar 2/16/1999 03:15'!
  23384. texture: aForm
  23385.     texture _ aForm! !
  23386.  
  23387. !B3DVertexRasterizer methodsFor: 'accessing'!
  23388. viewport
  23389.     ^viewport! !
  23390.  
  23391. !B3DVertexRasterizer methodsFor: 'accessing' stamp: 'ar 5/26/2000 15:30'!
  23392. viewport: aRectangle
  23393.     | r |
  23394.     r _ aRectangle.
  23395.     offset ifNotNil:[r _ r translateBy: offset].
  23396.     viewport _ B3DViewport origin: r origin corner: r corner.
  23397.     viewport toggleYScale.! !
  23398.  
  23399. !B3DVertexRasterizer methodsFor: 'accessing' stamp: 'ar 5/26/2000 15:17'!
  23400. viewportOffset
  23401.     "Return the viewport offset"
  23402.     ^offset! !
  23403.  
  23404. !B3DVertexRasterizer methodsFor: 'accessing' stamp: 'ar 5/26/2000 15:17'!
  23405. viewportOffset: aPoint
  23406.     "Set the viewport offset"
  23407.     offset _ aPoint! !
  23408.  
  23409. !B3DVertexRasterizer methodsFor: 'testing'!
  23410. needsClip
  23411.     "Return true if we need to clip polygons before rasterization.
  23412.     Generally, this should not be the case."
  23413.     ^self subclassResponsibility! !
  23414.  
  23415. !B3DVertexRasterizer methodsFor: 'processing' stamp: 'ar 2/16/1999 02:02'!
  23416. clearDepthBuffer
  23417.     "If the rasterizer uses a depth buffer, clear it."! !
  23418.  
  23419. !B3DVertexRasterizer methodsFor: 'processing' stamp: 'ar 5/28/2000 02:25'!
  23420. clearViewport: aColor
  23421.     "Clear the current viewport using the given color"
  23422.     target ifNotNil:[
  23423.         target 
  23424.             fill: viewport 
  23425.             rule: Form over 
  23426.             fillColor: aColor asColor
  23427.     ].! !
  23428.  
  23429. !B3DVertexRasterizer methodsFor: 'processing' stamp: 'ar 11/7/1999 18:04'!
  23430. processVertexBuffer: vb
  23431.     vbBounds _ nil.
  23432.     super processVertexBuffer: vb.
  23433.     ^vbBounds! !
  23434.  
  23435. !B3DVertexShader methodsFor: 'initialize' stamp: 'ar 2/17/1999 04:17'!
  23436. initialize
  23437.     super initialize.
  23438.     lights _ OrderedCollection new.
  23439.     material _ B3DMaterial new.
  23440.     materialStack _ OrderedCollection new: 10.! !
  23441.  
  23442. !B3DVertexShader methodsFor: 'initialize' stamp: 'ar 4/10/1999 22:55'!
  23443. reset
  23444.     super reset.
  23445.     lights _ OrderedCollection new.
  23446.     material _ B3DMaterial new.
  23447.     materialStack _ OrderedCollection new: 10.! !
  23448.  
  23449. !B3DVertexShader methodsFor: 'shading' stamp: 'ar 4/3/1999 20:10'!
  23450. processVertexBuffer: vb
  23451.     | colors emissionPart |
  23452.     colors _ B3DColor4Array new: vb vertexCount.
  23453.     "Load initial colors (e.g., emission part)"
  23454.     vb trackEmissionColor ifFalse:[
  23455.         emissionPart _ material emission.
  23456.         1 to: vb vertexCount do:[:i| colors at: i put: emissionPart].
  23457.     ] ifTrue:[
  23458.         1 to: vb vertexCount do:[:i| colors at: i put: (vb primitiveVertexAt: i) b3dColor].
  23459.     ].
  23460.     lights do:[:light|
  23461.         light shadeVertexBuffer: vb with: material into: colors.
  23462.     ].
  23463.     colors clampAllFrom: 0.0 to: 1.0.
  23464.     vb vertexArray upTo: vb vertexCount doWithIndex:[:vtx :i| vtx color: (colors at: i)].
  23465. ! !
  23466.  
  23467. !B3DVertexShader methodsFor: 'accessing' stamp: 'ar 2/17/1999 04:14'!
  23468. addLight: aLightSource
  23469.     lights add: aLightSource.
  23470.     ^lights size! !
  23471.  
  23472. !B3DVertexShader methodsFor: 'accessing' stamp: 'ar 2/7/1999 19:36'!
  23473. material
  23474.     ^material! !
  23475.  
  23476. !B3DVertexShader methodsFor: 'accessing' stamp: 'ar 2/7/1999 19:36'!
  23477. material: aMaterial
  23478.     material _ aMaterial.! !
  23479.  
  23480. !B3DVertexShader methodsFor: 'accessing' stamp: 'ar 2/7/1999 16:19'!
  23481. materialColor: aColor
  23482.     material ambientPart: aColor.
  23483.     material diffusePart: aColor.
  23484.     material specularPart: aColor.! !
  23485.  
  23486. !B3DVertexShader methodsFor: 'accessing' stamp: 'ar 2/7/1999 19:35'!
  23487. popMaterial
  23488.     material _ materialStack removeLast.! !
  23489.  
  23490. !B3DVertexShader methodsFor: 'accessing' stamp: 'ar 2/7/1999 19:35'!
  23491. pushMaterial
  23492.     materialStack addLast: material.! !
  23493.  
  23494. !B3DVertexShader methodsFor: 'accessing' stamp: 'ar 2/17/1999 04:16'!
  23495. removeLight: lightIndex
  23496.     "Remove the light with the given index"
  23497.     (lightIndex < 1 or:[lightIndex > lights size]) ifTrue:[^nil].
  23498.     lights at: lightIndex put: nil. "So we don't change the indexes"! !
  23499.  
  23500. !B3DVertexShader class methodsFor: 'testing' stamp: 'ar 2/14/1999 01:41'!
  23501. isAvailable
  23502.     "Return true if this part of the engine is available"
  23503.     ^true! !
  23504.  
  23505. !B3DVertexTransformer methodsFor: 'initialize' stamp: 'ar 4/18/1999 02:23'!
  23506. initialize
  23507.     super initialize.
  23508.     modelMatrix _ B3DMatrix4x4 identity.
  23509.     viewMatrix _ B3DMatrix4x4 identity.
  23510.     textureMatrix _ B3DMatrix4x4 identity.
  23511.     currentMatrix _ modelMatrix.
  23512.     matrixStack _ OrderedCollection new: 30.
  23513.     matrixStack resetTo: 1.
  23514.     needsUpdate _ false.! !
  23515.  
  23516. !B3DVertexTransformer methodsFor: 'initialize' stamp: 'ar 4/16/1999 07:59'!
  23517. reset
  23518.     super reset.
  23519.     modelMatrix := B3DMatrix4x4 identity.
  23520.     viewMatrix := B3DMatrix4x4 identity.
  23521.     textureMatrix := B3DMatrix4x4 identity.
  23522.     currentMatrix := modelMatrix.
  23523.     matrixStack := OrderedCollection new: 30.
  23524.     matrixStack resetTo: 1.
  23525.     needsUpdate := false.! !
  23526.  
  23527. !B3DVertexTransformer methodsFor: 'public' stamp: 'ar 8/19/1999 16:31'!
  23528. transformDirection: aVector3
  23529.     | zero one |
  23530.     zero _ B3DVector3 new.
  23531.     one _ zero + aVector3.
  23532.     zero _ self transformPosition: zero.
  23533.     one _ self transformPosition: one.
  23534.     ^one - zero! !
  23535.  
  23536. !B3DVertexTransformer methodsFor: 'public' stamp: 'ar 2/8/1999 01:33'!
  23537. transformPosition: aVector3
  23538.     | pVtx |
  23539.     pVtx _ B3DPrimitiveVertex new.
  23540.     pVtx position: aVector3.
  23541.     self privateTransformPrimitiveVertex: pVtx byModelView: self modelViewMatrix.
  23542.     ^pVtx position! !
  23543.  
  23544. !B3DVertexTransformer methodsFor: 'accessing' stamp: 'ar 2/2/1999 18:58'!
  23545. currentMatrix
  23546.     ^currentMatrix! !
  23547.  
  23548. !B3DVertexTransformer methodsFor: 'accessing' stamp: 'ar 2/2/1999 18:58'!
  23549. matrixMode
  23550.     currentMatrix == modelMatrix ifTrue:[^#modelView].
  23551.     currentMatrix == viewMatrix ifTrue:[^#projection].
  23552.     currentMatrix == textureMatrix ifTrue:[^#texture].
  23553.     self error:'Bad matrix state'.! !
  23554.  
  23555. !B3DVertexTransformer methodsFor: 'accessing' stamp: 'ar 2/2/1999 18:58'!
  23556. matrixMode: aSymbol
  23557.     aSymbol == #modelView ifTrue:[currentMatrix := modelMatrix. ^self].
  23558.     aSymbol == #projection ifTrue:[currentMatrix := viewMatrix. ^self].
  23559.     aSymbol == #texture ifTrue:[currentMatrix := textureMatrix. ^self].
  23560.     self error:'Bad matrix mode'.! !
  23561.  
  23562. !B3DVertexTransformer methodsFor: 'accessing' stamp: 'ar 2/2/1999 18:58'!
  23563. modelViewMatrix
  23564.     ^modelMatrix! !
  23565.  
  23566. !B3DVertexTransformer methodsFor: 'accessing' stamp: 'ar 2/2/1999 18:59'!
  23567. popMatrix
  23568.     "Pop the current matrix from the stack"
  23569.     matrixStack isEmpty ifTrue:[^self error:'Empty matrix stack'].
  23570.     currentMatrix loadFrom: matrixStack removeLast.! !
  23571.  
  23572. !B3DVertexTransformer methodsFor: 'accessing' stamp: 'ar 2/2/1999 18:59'!
  23573. projectionMatrix
  23574.     ^viewMatrix! !
  23575.  
  23576. !B3DVertexTransformer methodsFor: 'accessing' stamp: 'ar 2/2/1999 18:59'!
  23577. pushMatrix
  23578.     "Push the current matrix"
  23579.     | theMatrix |
  23580.     theMatrix := B3DMatrix4x4 new.
  23581.     theMatrix loadFrom: currentMatrix.
  23582.     matrixStack addLast: theMatrix.! !
  23583.  
  23584. !B3DVertexTransformer methodsFor: 'modifying' stamp: 'ar 2/2/1999 19:00'!
  23585. loadIdentity
  23586.     currentMatrix setIdentity.
  23587.     needsUpdate := true.! !
  23588.  
  23589. !B3DVertexTransformer methodsFor: 'modifying' stamp: 'ar 2/2/1999 19:00'!
  23590. loadMatrix: aMatrix
  23591.     currentMatrix loadFrom: aMatrix.
  23592.     needsUpdate := true.! !
  23593.  
  23594. !B3DVertexTransformer methodsFor: 'modifying' stamp: 'ar 2/7/1999 01:39'!
  23595. lookFrom: position to: target up: upDirection
  23596.     "create a matrix such that we look from eyePoint to centerPoint using upDirection"
  23597.     | xDir yDir zDir m |
  23598.     "calculate z vector"
  23599.     zDir _ target - position.
  23600.     zDir safelyNormalize.
  23601.     "calculate x vector"
  23602.     xDir _ upDirection cross: zDir.
  23603.     xDir safelyNormalize.
  23604.     "recalc y vector"
  23605.     yDir _ zDir cross: xDir.
  23606.     yDir safelyNormalize.
  23607.     m := B3DMatrix4x4 new.
  23608.     m    a11: xDir x;        a12: xDir y;        a13: xDir z;        a14: 0.0;
  23609.         a21: yDir x;        a22: yDir y;        a23: yDir z;        a24: 0.0;
  23610.         a31: zDir x;        a32: zDir y;        a33: zDir z;        a34: 0.0;
  23611.         a41: 0.0;            a42: 0.0;        a43: 0.0;        a44: 1.0.
  23612.     self transformBy: m.
  23613.     self translateBy: position negated.! !
  23614.  
  23615. !B3DVertexTransformer methodsFor: 'modifying' stamp: 'ar 2/2/1999 19:00'!
  23616. multiplyMatrix: aMatrix
  23617.     "Multiply aMatrix with the current matrix"
  23618.     currentMatrix *= aMatrix! !
  23619.  
  23620. !B3DVertexTransformer methodsFor: 'modifying'!
  23621. rotateBy: aRotation
  23622.     self transformBy: aRotation asMatrix4x4.! !
  23623.  
  23624. !B3DVertexTransformer methodsFor: 'modifying'!
  23625. scaleBy: aVector
  23626.     self transformBy: (B3DMatrix4x4 identity setScale: aVector)! !
  23627.  
  23628. !B3DVertexTransformer methodsFor: 'modifying' stamp: 'ar 2/2/1999 19:01'!
  23629. scaleByX: x y: y z: z
  23630.     currentMatrix scaleByX: x y: y z: z.
  23631.     needsUpdate := true.! !
  23632.  
  23633. !B3DVertexTransformer methodsFor: 'modifying'!
  23634. transformBy: aTransformation
  23635.     self privateTransformMatrix: currentMatrix 
  23636.             with: aTransformation asMatrix4x4 
  23637.             into: currentMatrix.
  23638.     needsUpdate := true.! !
  23639.  
  23640. !B3DVertexTransformer methodsFor: 'modifying'!
  23641. translateBy: aVector
  23642.     "Add the translation defined by aVector to the current matrix"
  23643.     self transformBy: (B3DMatrix4x4 identity setTranslation: aVector).! !
  23644.  
  23645. !B3DVertexTransformer methodsFor: 'modifying' stamp: 'ar 2/2/1999 19:01'!
  23646. translateByX: x y: y z: z
  23647.     "Add the translation defined by aVector to the current matrix"
  23648.     currentMatrix translateByX: x y: y z: z.
  23649.     needsUpdate := true.! !
  23650.  
  23651. !B3DVertexTransformer methodsFor: 'processing' stamp: 'ar 4/18/1999 02:23'!
  23652. processVertexBuffer: vb
  23653.     ^self processVertexBuffer: vb modelView: self modelViewMatrix projection: self projectionMatrix! !
  23654.  
  23655. !B3DVertexTransformer methodsFor: 'processing' stamp: 'ar 4/18/1999 02:22'!
  23656. processVertexBuffer: vb modelView: modelViewMatrix projection: projectionMatrix
  23657.     ^self privateTransformVB: vb vertexArray 
  23658.             count: vb vertexCount
  23659.             modelViewMatrix: modelViewMatrix
  23660.             projectionMatrix: projectionMatrix
  23661.             flags: vb flags! !
  23662.  
  23663. !B3DVertexTransformer methodsFor: 'view transformation'!
  23664. ortho: aFrustum
  23665.     viewMatrix _ aFrustum asFrustum asOrthoMatrix.
  23666.     needsUpdate _ true.! !
  23667.  
  23668. !B3DVertexTransformer methodsFor: 'view transformation'!
  23669. perspective: aPerspectiveOrFrustum
  23670.     viewMatrix _ aPerspectiveOrFrustum asFrustum asPerspectiveMatrix.
  23671.     needsUpdate _ true.! !
  23672.  
  23673. !B3DVertexTransformer methodsFor: 'private-transforming' stamp: 'ar 2/17/1999 04:19'!
  23674. privateTransformMatrix: m1 with: m2 into: m3
  23675.     "Perform a 4x4 matrix multiplication
  23676.         m2 * m1 = m3
  23677.     being equal to first transforming points by m2 and then by m1.
  23678.     Note that m1 may be identical to m3."
  23679.     | c1 c2 c3 c4 |
  23680.     m2 == m3 ifTrue:[^self error:'Argument and result matrix identical'].
  23681.     c1 _ ((m1 a11 * m2 a11) + (m1 a12 * m2 a21) + 
  23682.                 (m1 a13 * m2 a31) + (m1 a14 * m2 a41)).
  23683.     c2 _ ((m1 a11 * m2 a12) + (m1 a12 * m2 a22) + 
  23684.                 (m1 a13 * m2 a32) + (m1 a14 * m2 a42)).
  23685.     c3 _ ((m1 a11 * m2 a13) + (m1 a12 * m2 a23) + 
  23686.                 (m1 a13 * m2 a33) + (m1 a14 * m2 a43)).
  23687.     c4 _ ((m1 a11 * m2 a14) + (m1 a12 * m2 a24) + 
  23688.                 (m1 a13 * m2 a34) + (m1 a14 * m2 a44)).
  23689.  
  23690.     m3 a11: c1; a12: c2; a13: c3; a14: c4.
  23691.  
  23692.     c1 _ ((m1 a21 * m2 a11) + (m1 a22 * m2 a21) + 
  23693.                 (m1 a23 * m2 a31) + (m1 a24 * m2 a41)).
  23694.     c2 _ ((m1 a21 * m2 a12) + (m1 a22 * m2 a22) + 
  23695.                 (m1 a23 * m2 a32) + (m1 a24 * m2 a42)).
  23696.     c3 _ ((m1 a21 * m2 a13) + (m1 a22 * m2 a23) + 
  23697.                 (m1 a23 * m2 a33) + (m1 a24 * m2 a43)).
  23698.     c4 _ ((m1 a21 * m2 a14) + (m1 a22 * m2 a24) + 
  23699.                 (m1 a23 * m2 a34) + (m1 a24 * m2 a44)).
  23700.  
  23701.     m3 a21: c1; a22: c2; a23: c3; a24: c4.
  23702.  
  23703.     c1 _ ((m1 a31 * m2 a11) + (m1 a32 * m2 a21) + 
  23704.                 (m1 a33 * m2 a31) + (m1 a34 * m2 a41)).
  23705.     c2 _ ((m1 a31 * m2 a12) + (m1 a32 * m2 a22) + 
  23706.                 (m1 a33 * m2 a32) + (m1 a34 * m2 a42)).
  23707.     c3 _ ((m1 a31 * m2 a13) + (m1 a32 * m2 a23) + 
  23708.                 (m1 a33 * m2 a33) + (m1 a34 * m2 a43)).
  23709.     c4 _ ((m1 a31 * m2 a14) + (m1 a32 * m2 a24) + 
  23710.                 (m1 a33 * m2 a34) + (m1 a34 * m2 a44)).
  23711.  
  23712.     m3 a31: c1; a32: c2; a33: c3; a34: c4.
  23713.  
  23714.     c1 _ ((m1 a41 * m2 a11) + (m1 a42 * m2 a21) + 
  23715.                 (m1 a43 * m2 a31) + (m1 a44 * m2 a41)).
  23716.     c2 _ ((m1 a41 * m2 a12) + (m1 a42 * m2 a22) + 
  23717.                 (m1 a43 * m2 a32) + (m1 a44 * m2 a42)).
  23718.     c3 _ ((m1 a41 * m2 a13) + (m1 a42 * m2 a23) + 
  23719.                 (m1 a43 * m2 a33) + (m1 a44 * m2 a43)).
  23720.     c4 _ ((m1 a41 * m2 a14) + (m1 a42 * m2 a24) + 
  23721.                 (m1 a43 * m2 a34) + (m1 a44 * m2 a44)).
  23722.  
  23723.     m3 a41: c1; a42: c2; a43: c3; a44: c4.! !
  23724.  
  23725. !B3DVertexTransformer methodsFor: 'private-transforming' stamp: 'ar 2/17/1999 04:20'!
  23726. privateTransformPrimitiveNormal: primitiveVertex byMatrix: aMatrix rescale: scaleNeeded
  23727.     | x y z rx ry rz dot |
  23728.     x _ primitiveVertex normalX.
  23729.     y _ primitiveVertex normalY.
  23730.     z _ primitiveVertex normalZ.
  23731.     rx := (x * aMatrix a11) + (y * aMatrix a12) + (z * aMatrix a13).
  23732.     ry := (x * aMatrix a21) + (y * aMatrix a22) + (z * aMatrix a23).
  23733.     rz := (x * aMatrix a31) + (y * aMatrix a32) + (z * aMatrix a33).
  23734.     scaleNeeded ifTrue:[
  23735.         dot _ (rx * rx) + (ry * ry) + (rz * rz).
  23736.         dot < 1.0e-20 ifTrue:[
  23737.             rx _ ry _ rz _ 0.0.
  23738.         ] ifFalse:[
  23739.             dot = 1.0 ifFalse:[
  23740.                 dot _ 1.0 / dot sqrt.
  23741.                 rx _ rx * dot.
  23742.                 ry _ ry * dot.
  23743.                 rz _ rz * dot.
  23744.             ].
  23745.         ].
  23746.     ].
  23747.     primitiveVertex normalX: rx.
  23748.     primitiveVertex normalY: ry.
  23749.     primitiveVertex normalZ: rz.
  23750. ! !
  23751.  
  23752. !B3DVertexTransformer methodsFor: 'private-transforming' stamp: 'ar 2/17/1999 04:20'!
  23753. privateTransformPrimitiveVertex: primitiveVertex byModelView: aMatrix
  23754.     | x y z rx ry rz rw oneOverW |
  23755.     x _ primitiveVertex positionX.
  23756.     y _ primitiveVertex positionY.
  23757.     z _ primitiveVertex positionZ.
  23758.     rx := (x * aMatrix a11) + (y * aMatrix a12) + (z * aMatrix a13) + aMatrix a14.
  23759.     ry := (x * aMatrix a21) + (y * aMatrix a22) + (z * aMatrix a23) + aMatrix a24.
  23760.     rz := (x * aMatrix a31) + (y * aMatrix a32) + (z * aMatrix a33) + aMatrix a34.
  23761.     rw := (x * aMatrix a41) + (y * aMatrix a42) + (z * aMatrix a43) + aMatrix a44.
  23762.     rw = 1.0 ifTrue:[
  23763.         primitiveVertex positionX: rx.
  23764.         primitiveVertex positionY: ry.
  23765.         primitiveVertex positionZ: rz.
  23766.     ] ifFalse:[
  23767.         rw = 0.0 
  23768.             ifTrue:[oneOverW _ 0.0]
  23769.             ifFalse:[oneOverW _ 1.0 / rw].
  23770.         primitiveVertex positionX: rx * oneOverW.
  23771.         primitiveVertex positionY: ry * oneOverW.
  23772.         primitiveVertex positionZ: rz * oneOverW.
  23773.     ].
  23774. ! !
  23775.  
  23776. !B3DVertexTransformer methodsFor: 'private-transforming' stamp: 'ar 2/8/1999 18:19'!
  23777. privateTransformPrimitiveVertex: primitiveVertex byModelViewWithoutW: aMatrix
  23778.     "Special case of aMatrix a41 = a42 = a43 = 0.0 and a44 = 1.0"
  23779.     | x y z rx ry rz |
  23780.     "Note: This is not supported by primitive level operations."
  23781.     self flag: #b3dPrimitive.
  23782.     x _ primitiveVertex positionX.
  23783.     y _ primitiveVertex positionY.
  23784.     z _ primitiveVertex positionZ.
  23785.     rx := (x * aMatrix a11) + (y * aMatrix a12) + (z * aMatrix a13) + aMatrix a14.
  23786.     ry := (x * aMatrix a21) + (y * aMatrix a22) + (z * aMatrix a23) + aMatrix a24.
  23787.     rz := (x * aMatrix a31) + (y * aMatrix a32) + (z * aMatrix a33) + aMatrix a34.
  23788.     primitiveVertex positionX: rx.
  23789.     primitiveVertex positionY: ry.
  23790.     primitiveVertex positionZ: rz.! !
  23791.  
  23792. !B3DVertexTransformer methodsFor: 'private-transforming' stamp: 'ar 2/17/1999 04:21'!
  23793. privateTransformPrimitiveVertex: primitiveVertex byProjection: aMatrix
  23794.     | x y z rx ry rz rw |
  23795.     x _ primitiveVertex positionX.
  23796.     y _ primitiveVertex positionY.
  23797.     z _ primitiveVertex positionZ.
  23798.     rx := (x * aMatrix a11) + (y * aMatrix a12) + (z * aMatrix a13) + aMatrix a14.
  23799.     ry := (x * aMatrix a21) + (y * aMatrix a22) + (z * aMatrix a23) + aMatrix a24.
  23800.     rz := (x * aMatrix a31) + (y * aMatrix a32) + (z * aMatrix a33) + aMatrix a34.
  23801.     rw := (x * aMatrix a41) + (y * aMatrix a42) + (z * aMatrix a43) + aMatrix a44.
  23802.     primitiveVertex rasterPosX: rx.
  23803.     primitiveVertex rasterPosY: ry.
  23804.     primitiveVertex rasterPosZ: rz.
  23805.     primitiveVertex rasterPosW: rw.! !
  23806.  
  23807. !B3DVertexTransformer methodsFor: 'private-transforming' stamp: 'ar 2/17/1999 04:22'!
  23808. privateTransformVB: vertexArray count: vertexCount modelViewMatrix: modelViewMatrix projectionMatrix: projectionMatrix flags: flags
  23809.     | noW |
  23810.     (modelViewMatrix a41 = 0.0 and:[
  23811.         modelViewMatrix a42 = 0.0 and:[
  23812.             modelViewMatrix a43 = 0.0 and:[
  23813.                 modelViewMatrix a44 = 1.0]]]) ifTrue:[noW _ true].
  23814.     noW ifTrue:[
  23815.         vertexArray upTo: vertexCount do:[:primitiveVertex|
  23816.             self privateTransformPrimitiveVertex: primitiveVertex
  23817.                 byModelViewWithoutW: modelViewMatrix.
  23818.             self privateTransformPrimitiveVertex: primitiveVertex
  23819.                 byProjection: projectionMatrix.
  23820.             (flags anyMask: VBVtxHasNormals)
  23821.                 ifTrue:[self privateTransformPrimitiveNormal: primitiveVertex
  23822.                             byMatrix: modelViewMatrix
  23823.                             rescale: true].
  23824.         ].
  23825.     ] ifFalse:[
  23826.         vertexArray upTo: vertexCount do:[:primitiveVertex|
  23827.             self privateTransformPrimitiveVertex: primitiveVertex
  23828.                 byModelView: modelViewMatrix.
  23829.             self privateTransformPrimitiveVertex: primitiveVertex
  23830.                 byProjection: projectionMatrix.
  23831.             (flags anyMask: VBVtxHasNormals)
  23832.                 ifTrue:[self privateTransformPrimitiveNormal: primitiveVertex
  23833.                             byMatrix: modelViewMatrix
  23834.                             rescale: true].
  23835.         ].
  23836.     ].! !
  23837.  
  23838. !B3DVertexTransformer class methodsFor: 'testing' stamp: 'ar 2/14/1999 01:41'!
  23839. isAvailable
  23840.     "Return true if this part of the engine is available"
  23841.     ^true! !
  23842.  
  23843. I represent a viewing frustum, defined by the following values:
  23844.  
  23845.     typedef struct B3DViewingFrustum {
  23846.         float left;
  23847.         float right;
  23848.         float top;
  23849.         float bottom;
  23850.         float near;
  23851.         float far;
  23852.     } B3DViewingFrustum;
  23853.  
  23854. The frustum can be converted into either a ortho matrix (having no perspective distortion) or a perspective matrix for use in the Balloon 3D render engine.!
  23855. !B3DViewingFrustum methodsFor: 'private'!
  23856. asOrthoMatrixInto: aB3DMatrix4x4
  23857.     | x y z tx ty tz dx dy dz |
  23858.     (self near <= 0.0 or:[self far <= 0.0]) ifTrue: [^self error:'Clipping plane error'].
  23859.     dx := self right - self left.
  23860.     dy := self top - self bottom.
  23861.     dz := self far - self near.
  23862.     x := dx * 0.5.
  23863.     y := dy * 0.5.
  23864.     z := dz * -0.5.
  23865.     tx := (self left + self right) / dx.
  23866.     ty := (self top + self bottom) / dy.
  23867.     tz := (self near + self far) / dz.
  23868.     aB3DMatrix4x4
  23869.         a11: x;        a12: 0.0;        a13: 0.0;        a14: tx;
  23870.         a21: 0.0;        a22: y;        a23: 0.0;    a24: ty;
  23871.         a31: 0.0;        a32: 0.0;    a33: z;        a34: tz;
  23872.         a41: 0.0;        a42: 0.0;    a43: 0.0;    a44: 1.0.
  23873.     ^aB3DMatrix4x4! !
  23874.  
  23875. !B3DViewingFrustum methodsFor: 'private' stamp: 'ar 2/7/1999 01:30'!
  23876. asPerspectiveMatrixInto: aB3DMatrix4x4
  23877.     | x y a b c d dx dy dz z2 |
  23878.     (self near <= 0.0 or:[self far <= 0.0 or:[self near >= self far]]) 
  23879.         ifTrue: [^self error:'Clipping plane error'].
  23880.     dx := self right - self left.
  23881.     dy := self top - self bottom.
  23882.     dz := self far - self near.
  23883.     z2 := 2.0 * self near.
  23884.     x := z2 / dx.
  23885.     y := z2 / dy.
  23886.     a := (self left + self right) / dx.
  23887.     b := (self top + self bottom) / dy.
  23888.     c := (self near + self far) "*negated*" / dz.
  23889.     d := (-2.0 * self near * self far) / dz.
  23890.     aB3DMatrix4x4
  23891.         a11: x;        a12: 0.0;        a13: a;        a14: 0.0;
  23892.         a21: 0.0;        a22: y;        a23: b;        a24: 0.0;
  23893.         a31: 0.0;        a32: 0.0;    a33: c;        a34: d;
  23894.         a41: 0.0;        a42: 0.0;    a43: "*-1*"1;        a44: 0.0.
  23895.     ^aB3DMatrix4x4! !
  23896.  
  23897. !B3DViewingFrustum methodsFor: 'private'!
  23898. computeFromNear: nearDistance far: farDistance fov: fieldOfView aspect: aspectRatio
  23899.     "Compute the viewing frustum from the given values"
  23900.     | top bottom |
  23901.     top := nearDistance * fieldOfView degreesToRadians tan.
  23902.     bottom := top negated.
  23903.     self left: bottom * aspectRatio.
  23904.     self right: top * aspectRatio.    
  23905.     self top: top.
  23906.     self bottom: bottom.
  23907.     self near: nearDistance.
  23908.     self far: farDistance.! !
  23909.  
  23910. !B3DViewingFrustum methodsFor: 'accessing'!
  23911. bottom
  23912.     ^self floatAt: 4.! !
  23913.  
  23914. !B3DViewingFrustum methodsFor: 'accessing'!
  23915. bottom: aFloat
  23916.     self floatAt: 4 put: aFloat! !
  23917.  
  23918. !B3DViewingFrustum methodsFor: 'accessing'!
  23919. far
  23920.     ^self floatAt: 6! !
  23921.  
  23922. !B3DViewingFrustum methodsFor: 'accessing'!
  23923. far: aFloat
  23924.     self floatAt: 6 put: aFloat! !
  23925.  
  23926. !B3DViewingFrustum methodsFor: 'accessing'!
  23927. left
  23928.     ^self floatAt: 1! !
  23929.  
  23930. !B3DViewingFrustum methodsFor: 'accessing'!
  23931. left: aFloat
  23932.     self floatAt: 1 put: aFloat! !
  23933.  
  23934. !B3DViewingFrustum methodsFor: 'accessing'!
  23935. near
  23936.     ^self floatAt: 5! !
  23937.  
  23938. !B3DViewingFrustum methodsFor: 'accessing'!
  23939. near: aFloat
  23940.     self floatAt: 5 put: aFloat! !
  23941.  
  23942. !B3DViewingFrustum methodsFor: 'accessing'!
  23943. right
  23944.     ^self floatAt: 2! !
  23945.  
  23946. !B3DViewingFrustum methodsFor: 'accessing'!
  23947. right: aFloat
  23948.     self floatAt: 2 put: aFloat! !
  23949.  
  23950. !B3DViewingFrustum methodsFor: 'accessing'!
  23951. top
  23952.     ^self floatAt: 3! !
  23953.  
  23954. !B3DViewingFrustum methodsFor: 'accessing'!
  23955. top: aFloat
  23956.     self floatAt: 3 put: aFloat! !
  23957.  
  23958. !B3DViewingFrustum methodsFor: 'converting'!
  23959. asFrustum
  23960.     ^self! !
  23961.  
  23962. !B3DViewingFrustum methodsFor: 'converting'!
  23963. asOrthoMatrix
  23964.     ^self asOrthoMatrixInto: B3DMatrix4x4 new! !
  23965.  
  23966. !B3DViewingFrustum methodsFor: 'converting'!
  23967. asPerspectiveMatrix
  23968.     ^self asPerspectiveMatrixInto: B3DMatrix4x4 new! !
  23969.  
  23970. !B3DViewingFrustum class methodsFor: 'instance creation'!
  23971. near: nearDistance far: farDistance fov: fieldOfView aspect: aspectRatio
  23972.     ^self new computeFromNear: nearDistance far: farDistance fov: fieldOfView aspect: aspectRatio! !
  23973.  
  23974. !B3DViewingFrustum class methodsFor: 'instance creation'!
  23975. numElements
  23976.     ^6! !
  23977.  
  23978. I represent a viewport for the Ballon 3D graphics engine. Since all positions are computed in the unit-coordinate system (-1,-1,-1) (1,1,1) after the render pipeline has completed, I am used to map these positions into the physical (pixel) coordinates of the output device before rasterization takes place.
  23979.  
  23980. Instance variables:
  23981.     center     <Point>    The center of the viewport
  23982.     scale     <Point>    The scale for points!
  23983. !B3DViewport methodsFor: 'mapping'!
  23984. asMatrixTransform2x3
  23985.     ^(MatrixTransform2x3 withScale: scale) offset: center! !
  23986.  
  23987. !B3DViewport methodsFor: 'mapping'!
  23988. mapVertex4: aVector
  23989.     | w x y oneOverW |
  23990.     w _ aVector w.
  23991.     w = 1.0 ifTrue:[
  23992.         x _ aVector x.
  23993.         y _ aVector y.
  23994.     ] ifFalse:[
  23995.         w = 0.0
  23996.             ifTrue:[oneOverW _ 0.0]
  23997.             ifFalse:[oneOverW _ 1.0 / w].
  23998.         x _ aVector x * oneOverW.
  23999.         y _ aVector y * oneOverW.
  24000.     ].
  24001.     ^((x@y) * scale + center) truncated! !
  24002.  
  24003. !B3DViewport methodsFor: 'private' stamp: 'ar 2/8/1999 21:45'!
  24004. setOrigin: topLeft corner: bottomRight
  24005.     super setOrigin: topLeft corner: bottomRight.
  24006.     center _ (self origin + self corner) / 2.0.
  24007.     scale _ corner - center + (0.5@-0.5). "Rasterizer offset"! !
  24008.  
  24009. !B3DViewport methodsFor: 'private' stamp: 'ar 2/7/1999 01:42'!
  24010. toggleYScale
  24011.     scale _ scale x @ scale y negated.! !
  24012.  
  24013. !B3DViewport methodsFor: 'accessing' stamp: 'ar 2/15/1999 02:53'!
  24014. aspectRatio
  24015.     ^self width asFloat / self height asFloat! !
  24016.  
  24017. !B3DViewport methodsFor: 'accessing' stamp: 'ar 4/3/1999 20:29'!
  24018. center
  24019.     ^center! !
  24020.  
  24021. !B3DViewport methodsFor: 'accessing' stamp: 'ar 4/3/1999 20:29'!
  24022. scale
  24023.     ^scale! !
  24024.  
  24025. This morph incorporates tiling and regular motion with the intent of supporting, eg, panning of endless (toroidal) backgrounds.
  24026.  
  24027. The idea is that embedded morphs get displayed at a moving offset relative to my position.  Moreover this display is tiled according to the bounding box of the submorphs (subBounds), as much as necesary to fill the rest of my bounds.!
  24028. !BackgroundMorph methodsFor: 'as yet unclassified' stamp: 'ar 6/17/1999 01:06'!
  24029. drawOn: aCanvas
  24030.     "The tiling is solely determined by bounds, subBounds and offset.
  24031.     The extent of display is determined by bounds and the clipRect of the canvas."
  24032.     | start d subBnds |
  24033.     submorphs isEmpty ifTrue: [^ super drawOn: aCanvas].
  24034.     subBnds _ self subBounds.
  24035.     running ifFalse:
  24036.         [super drawOn: aCanvas.
  24037.         ^ aCanvas fillRectangle: subBnds color: Color lightBlue].
  24038.     start _ subBnds topLeft + offset - bounds topLeft - (1@1) \\ subBnds extent - subBnds extent + (1@1).
  24039.     d _ subBnds topLeft - bounds topLeft.
  24040. "Sensor redButtonPressed ifTrue: [self halt]."
  24041.     start x to: bounds width - 1 by: subBnds width do:
  24042.         [:x |
  24043.         start y to: bounds height - 1 by: subBnds height do:
  24044.             [:y | aCanvas translateBy: (x@y) - d clippingTo: bounds
  24045.                 during:[:tileCanvas| self drawSubmorphsOn: tileCanvas]]].! !
  24046.  
  24047. !BackgroundMorph methodsFor: 'as yet unclassified' stamp: 'ar 5/29/1999 08:32'!
  24048. fullDrawOn: aCanvas
  24049.  
  24050.     running ifFalse: [
  24051.         ^aCanvas clipBy: (bounds translateBy: aCanvas origin)
  24052.                 during:[:clippedCanvas| super fullDrawOn: clippedCanvas]].
  24053.     aCanvas drawMorph: self.
  24054. ! !
  24055.  
  24056. I represent an unordered collection of possibly duplicate elements.
  24057.     
  24058. I store these elements in a dictionary, tallying up occurrences of equal objects. Because I store an occurrence only once, my clients should beware that objects they store will not necessarily be retrieved such that == is true. If the client cares, a subclass of me should be created.!
  24059. !Bag methodsFor: 'accessing' stamp: 'sma 5/12/2000 17:23'!
  24060. at: index 
  24061.     self errorNotKeyed! !
  24062.  
  24063. !Bag methodsFor: 'accessing' stamp: 'sma 5/12/2000 17:23'!
  24064. at: index put: anObject 
  24065.     self errorNotKeyed! !
  24066.  
  24067. !Bag methodsFor: 'accessing' stamp: 'tao 1/5/2000 18:25'!
  24068. cumulativeCounts
  24069.     "Answer with a collection of cumulative percents covered by elements so far."
  24070.     | s n |
  24071.     s _ self size / 100.0. n _ 0.
  24072.     ^ self sortedCounts asArray collect:
  24073.         [:a | n _ n + a key. (n / s roundTo: 0.1) -> a value]! !
  24074.  
  24075. !Bag methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:35'!
  24076. size
  24077.     "Answer how many elements the receiver contains."
  24078.  
  24079.     | tally |
  24080.     tally _ 0.
  24081.     contents do: [:each | tally _ tally + each].
  24082.     ^ tally! !
  24083.  
  24084. !Bag methodsFor: 'adding' stamp: 'sma 5/12/2000 17:18'!
  24085. add: newObject 
  24086.     "Include newObject as one of the receiver's elements. Answer newObject."
  24087.  
  24088.     ^ self add: newObject withOccurrences: 1! !
  24089.  
  24090. !Bag methodsFor: 'adding' stamp: 'sma 5/12/2000 17:20'!
  24091. add: newObject withOccurrences: anInteger 
  24092.     "Add newObject anInteger times to the receiver. Answer newObject."
  24093.  
  24094.     contents at: newObject put: (contents at: newObject ifAbsent: [0]) + anInteger.
  24095.     ^ newObject! !
  24096.  
  24097. !Bag methodsFor: 'converting' stamp: 'sma 5/12/2000 14:34'!
  24098. asBag
  24099.     ^ self! !
  24100.  
  24101. !Bag methodsFor: 'converting' stamp: 'sma 5/12/2000 14:30'!
  24102. asSet
  24103.     "Answer a set with the elements of the receiver."
  24104.  
  24105.     ^ contents keys! !
  24106.  
  24107. !Bag methodsFor: 'copying' stamp: 'sma 5/12/2000 14:53'!
  24108. copy
  24109.     ^ self shallowCopy setContents: contents copy! !
  24110.  
  24111. !Bag methodsFor: 'private' stamp: 'sma 5/12/2000 14:49'!
  24112. setContents: aDictionary
  24113.     contents _ aDictionary! !
  24114.  
  24115. !Bag methodsFor: 'removing' stamp: 'sma 5/12/2000 14:32'!
  24116. remove: oldObject ifAbsent: exceptionBlock 
  24117.     "Refer to the comment in Collection|remove:ifAbsent:."
  24118.  
  24119.     | count |
  24120.     count _ contents at: oldObject ifAbsent: [^ exceptionBlock value].
  24121.     count = 1
  24122.         ifTrue: [contents removeKey: oldObject]
  24123.         ifFalse: [contents at: oldObject put: count - 1].
  24124.     ^ oldObject! !
  24125.  
  24126. !Bag class methodsFor: 'instance creation' stamp: 'sma 5/12/2000 13:31'!
  24127. new
  24128.     ^ self new: 4! !
  24129.  
  24130. !Bag class methodsFor: 'instance creation' stamp: 'sma 5/12/2000 14:49'!
  24131. new: nElements
  24132.     ^ super new setContents: (Dictionary new: nElements)! !
  24133.  
  24134. !Bag class methodsFor: 'instance creation' stamp: 'sma 5/12/2000 17:17'!
  24135. newFrom: aCollection 
  24136.     "Answer an instance of me containing the same elements as aCollection."
  24137.  
  24138.     ^ self withAll: aCollection
  24139.  
  24140. "Examples:
  24141.     Bag newFrom: {1. 2. 3. 3}
  24142.     {1. 2. 3. 3} as: Bag
  24143. "! !
  24144.  
  24145. !BalloonBezierSimulation methodsFor: 'accessing' stamp: 'ar 10/27/1998 20:45'!
  24146. end
  24147.     ^end! !
  24148.  
  24149. !BalloonBezierSimulation methodsFor: 'accessing' stamp: 'ar 10/27/1998 20:45'!
  24150. end: aPoint
  24151.     end _ aPoint! !
  24152.  
  24153. !BalloonBezierSimulation methodsFor: 'accessing' stamp: 'ar 10/30/1998 01:57'!
  24154. inTangent
  24155.     "Return the tangent at the start point"
  24156.     ^via - start! !
  24157.  
  24158. !BalloonBezierSimulation methodsFor: 'accessing' stamp: 'ar 10/27/1998 20:45'!
  24159. initialX
  24160.     ^start y <= end y
  24161.         ifTrue:[start x]
  24162.         ifFalse:[end x]! !
  24163.  
  24164. !BalloonBezierSimulation methodsFor: 'accessing' stamp: 'ar 10/27/1998 20:45'!
  24165. initialY
  24166.     ^start y <= end y
  24167.         ifTrue:[start y]
  24168.         ifFalse:[end y]! !
  24169.  
  24170. !BalloonBezierSimulation methodsFor: 'accessing' stamp: 'ar 10/27/1998 20:45'!
  24171. initialZ
  24172.     ^0 "Assume no depth given"! !
  24173.  
  24174. !BalloonBezierSimulation methodsFor: 'accessing' stamp: 'ar 10/30/1998 01:57'!
  24175. outTangent
  24176.     "Return the tangent at the end point"
  24177.     ^end - via! !
  24178.  
  24179. !BalloonBezierSimulation methodsFor: 'accessing' stamp: 'ar 10/27/1998 20:45'!
  24180. start
  24181.     ^start! !
  24182.  
  24183. !BalloonBezierSimulation methodsFor: 'accessing' stamp: 'ar 10/27/1998 20:45'!
  24184. start: aPoint
  24185.     start _ aPoint! !
  24186.  
  24187. !BalloonBezierSimulation methodsFor: 'accessing' stamp: 'ar 10/27/1998 20:45'!
  24188. via
  24189.     ^via! !
  24190.  
  24191. !BalloonBezierSimulation methodsFor: 'accessing' stamp: 'ar 10/27/1998 20:45'!
  24192. via: aPoint
  24193.     via _ aPoint! !
  24194.  
  24195. !BalloonBezierSimulation methodsFor: 'computing' stamp: 'ar 10/27/1998 20:46'!
  24196. computeInitialStateFrom: source with: transformation
  24197.     "Compute the initial state in the receiver."
  24198.     start _ (transformation localPointToGlobal: source start) asIntegerPoint.
  24199.     end _ (transformation localPointToGlobal: source end) asIntegerPoint.
  24200.     via _ (transformation localPointToGlobal: source via) asIntegerPoint.! !
  24201.  
  24202. !BalloonBezierSimulation methodsFor: 'computing' stamp: 'ar 10/30/1998 02:39'!
  24203. computeSplitAt: t
  24204.     "Split the receiver at the parametric value t"
  24205.     | left right newVia1 newVia2 newPoint |
  24206.     left _ self clone.
  24207.     right _ self clone.
  24208.     "Compute new intermediate points"
  24209.     newVia1 _ (via - start) * t + start.
  24210.     newVia2 _ (end - via) * t + via.
  24211.     "Compute new point on curve"
  24212.     newPoint _ ((newVia1 - newVia2) * t + newVia2) asIntegerPoint.
  24213.     left via: newVia1 asIntegerPoint.
  24214.     left end: newPoint.
  24215.     right start: newPoint.
  24216.     right via: newVia2 asIntegerPoint.
  24217.     ^Array with: left with: right! !
  24218.  
  24219. !BalloonBezierSimulation methodsFor: 'computing' stamp: 'ar 10/30/1998 01:34'!
  24220. floatStepToFirstScanLineAt: yValue in: edgeTableEntry
  24221.     "Float version of forward differencing"
  24222.     |  startX endX startY endY deltaY fwX1 fwX2 fwY1 fwY2 
  24223.     steps scaledStepSize squaredStepSize |
  24224.     (end y) >= (start y) ifTrue:[
  24225.         startX _ start x.    endX _ end x.
  24226.         startY _ start y.    endY _ end y.
  24227.     ] ifFalse:[
  24228.         startX _ end x.    endX _ start x.
  24229.         startY _ end y.    endY _ start y.
  24230.     ].
  24231.  
  24232.     deltaY _ endY - startY.
  24233.  
  24234.     "Quickly check if the line is visible at all"
  24235.     (yValue >= endY or:[deltaY = 0]) ifTrue:[
  24236.         ^edgeTableEntry lines: 0].
  24237.  
  24238.     fwX1 _ (startX + endX - (2 * via x)) asFloat.
  24239.     fwX2 _ (via x - startX * 2) asFloat.
  24240.     fwY1 _ (startY + endY - (2 * via y)) asFloat.
  24241.     fwY2 _ ((via y - startY) * 2) asFloat.
  24242.     steps _ deltaY asInteger * 2.
  24243.     scaledStepSize _ 1.0 / steps asFloat.
  24244.     squaredStepSize _ scaledStepSize * scaledStepSize.
  24245.     fwDx _ fwX2 * scaledStepSize.
  24246.     fwDDx _ 2.0 * fwX1 * squaredStepSize.
  24247.     fwDy _ fwY2 * scaledStepSize.
  24248.     fwDDy _ 2.0 * fwY1 * squaredStepSize.
  24249.     fwDx _ fwDx + (fwDDx * 0.5).
  24250.     fwDy _ fwDy + (fwDDy * 0.5).
  24251.  
  24252.     lastX _ startX asFloat.
  24253.     lastY _ startY asFloat.
  24254.  
  24255.     "self xDirection: xDir.
  24256.     self yDirection: yDir."
  24257.     edgeTableEntry xValue: startX.
  24258.     edgeTableEntry yValue: startY.
  24259.     edgeTableEntry zValue: 0.
  24260.     edgeTableEntry lines: deltaY.
  24261.  
  24262.     "If not at first scan line then step down to yValue"
  24263.     yValue = startY ifFalse:[
  24264.         self stepToNextScanLineAt: yValue in: edgeTableEntry.
  24265.         "And adjust remainingLines"
  24266.         edgeTableEntry lines: deltaY - (yValue - startY).
  24267.     ].! !
  24268.  
  24269. !BalloonBezierSimulation methodsFor: 'computing' stamp: 'ar 10/30/1998 02:45'!
  24270. floatStepToNextScanLineAt: yValue in: edgeTableEntry
  24271.     "Float version of forward differencing"
  24272.     [yValue asFloat > lastY] whileTrue:[
  24273.         (fwDx < -50.0 or:[fwDx > 50.0]) ifTrue:[self halt].
  24274.         (fwDy < -50.0 or:[fwDy > 50.0]) ifTrue:[self halt].
  24275.         (fwDDx < -50.0 or:[fwDDx > 50.0]) ifTrue:[self halt].
  24276.         (fwDDy < -50.0 or:[fwDDy > 50.0]) ifTrue:[self halt].
  24277.         lastX _ lastX + fwDx.
  24278.         lastY _ lastY + fwDy.
  24279.         fwDx _ fwDx + fwDDx.
  24280.         fwDy _ fwDy + fwDDy.
  24281.     ].
  24282.     edgeTableEntry xValue: lastX asInteger.
  24283.     edgeTableEntry zValue: 0.! !
  24284.  
  24285. !BalloonBezierSimulation methodsFor: 'computing' stamp: 'ar 10/30/1998 16:23'!
  24286. intStepToFirstScanLineAt: yValue in: edgeTableEntry
  24287.     "Scaled integer version of forward differencing"
  24288.     |  startX endX startY endY deltaY fwX1 fwX2 fwY1 fwY2 
  24289.      scaledStepSize squaredStepSize |
  24290.     (end y) >= (start y) ifTrue:[
  24291.         startX _ start x.    endX _ end x.
  24292.         startY _ start y.    endY _ end y.
  24293.     ] ifFalse:[
  24294.         startX _ end x.    endX _ start x.
  24295.         startY _ end y.    endY _ start y.
  24296.     ].
  24297.  
  24298.     deltaY _ endY - startY.
  24299.  
  24300.     "Quickly check if the line is visible at all"
  24301.     (yValue >= endY or:[deltaY = 0]) ifTrue:[
  24302.         ^edgeTableEntry lines: 0].
  24303.  
  24304.     fwX1 _ (startX + endX - (2 * via x)).
  24305.     fwX2 _ (via x - startX * 2).
  24306.     fwY1 _ (startY + endY - (2 * via y)).
  24307.     fwY2 _ ((via y - startY) * 2).
  24308.     maxSteps _ deltaY asInteger * 2.
  24309.     scaledStepSize _ 16r1000000 // maxSteps.
  24310.     "@@: Okay, we need some fancy 64bit multiplication here"
  24311.     squaredStepSize _ self absoluteSquared8Dot24: scaledStepSize.
  24312.     squaredStepSize = ((scaledStepSize * scaledStepSize) bitShift: -24)
  24313.         ifFalse:[self error:'Bad computation'].
  24314.     fwDx _ fwX2 * scaledStepSize.
  24315.     fwDDx _ 2 * fwX1 * squaredStepSize.
  24316.     fwDy _ fwY2 * scaledStepSize.
  24317.     fwDDy _ 2 * fwY1 * squaredStepSize.
  24318.     fwDx _ fwDx + (fwDDx // 2).
  24319.     fwDy _ fwDy + (fwDDy // 2).
  24320.  
  24321.     self validateIntegerRange.
  24322.  
  24323.     lastX _ startX * 256.
  24324.     lastY _ startY * 256.
  24325.  
  24326.     edgeTableEntry xValue: startX.
  24327.     edgeTableEntry yValue: startY.
  24328.     edgeTableEntry zValue: 0.
  24329.     edgeTableEntry lines: deltaY.
  24330.  
  24331.     "If not at first scan line then step down to yValue"
  24332.     yValue = startY ifFalse:[
  24333.         self stepToNextScanLineAt: yValue in: edgeTableEntry.
  24334.         "And adjust remainingLines"
  24335.         edgeTableEntry lines: deltaY - (yValue - startY).
  24336.     ].! !
  24337.  
  24338. !BalloonBezierSimulation methodsFor: 'computing' stamp: 'ar 10/30/1998 04:02'!
  24339. intStepToNextScanLineAt: yValue in: edgeTableEntry
  24340.     "Scaled integer version of forward differencing"
  24341.     [maxSteps >= 0 and:[yValue * 256 > lastY]] whileTrue:[
  24342.         self validateIntegerRange.
  24343.         lastX _ lastX + ((fwDx + 16r8000) // 16r10000).
  24344.         lastY _ lastY + ((fwDy + 16r8000) // 16r10000).
  24345.         fwDx _ fwDx + fwDDx.
  24346.         fwDy _ fwDy + fwDDy.
  24347.         maxSteps _ maxSteps - 1.
  24348.     ].
  24349.     edgeTableEntry xValue: lastX // 256.
  24350.     edgeTableEntry zValue: 0.! !
  24351.  
  24352. !BalloonBezierSimulation methodsFor: 'computing' stamp: 'ar 10/29/1998 22:14'!
  24353. isMonoton
  24354.     "Return true if the receiver is monoton along the y-axis,
  24355.     e.g., check if the tangents have the same sign"
  24356.     ^(via y - start y) * (end y - via y) >= 0! !
  24357.  
  24358. !BalloonBezierSimulation methodsFor: 'computing' stamp: 'ar 10/31/1998 16:36'!
  24359. stepToFirstScanLineAt: yValue in: edgeTableEntry
  24360.     "Compute the initial x value for the scan line at yValue"
  24361.     ^self intStepToFirstScanLineAt: yValue in: edgeTableEntry! !
  24362.  
  24363. !BalloonBezierSimulation methodsFor: 'computing' stamp: 'ar 10/30/1998 03:40'!
  24364. stepToNextScanLineAt: yValue in: edgeTableEntry
  24365.     "Compute the next x value for the scan line at yValue.
  24366.     This message is sent during incremental updates. 
  24367.     The yValue parameter is passed in here for edges
  24368.     that have more complicated computations,"
  24369.     ^self intStepToNextScanLineAt: yValue in: edgeTableEntry! !
  24370.  
  24371. !BalloonBezierSimulation methodsFor: 'computing' stamp: 'ar 11/1/1998 00:31'!
  24372. subdivide
  24373.     "Subdivide the receiver"
  24374.     | dy dx |
  24375.     "Test 1: If the bezier curve is not monoton in Y, we need a subdivision"
  24376.     self isMonoton ifFalse:[
  24377.         MonotonSubdivisions _ MonotonSubdivisions + 1.
  24378.         ^self subdivideToBeMonoton].
  24379.  
  24380.     "Test 2: If the receiver is horizontal, don't do anything"
  24381.     (end y = start y) ifTrue:[^nil].
  24382.  
  24383.     "Test 3: If the receiver can be represented as a straight line,
  24384.             make a line from the receiver and declare it invalid"
  24385.     ((end - start) crossProduct: (via - start)) = 0 ifTrue:[
  24386.         LineConversions _ LineConversions + 1.
  24387.         ^self subdivideToBeLine].
  24388.  
  24389.     "Test 4: If the height of the curve exceeds 256 pixels, subdivide 
  24390.             (forward differencing is numerically not very stable)"
  24391.     dy _ end y - start y.
  24392.     dy < 0 ifTrue:[dy _ dy negated].
  24393.     (dy > 255) ifTrue:[
  24394.         HeightSubdivisions _ HeightSubdivisions + 1.
  24395.         ^self subdivideAt: 0.5].
  24396.  
  24397.     "Test 5: Check if the incremental values could possibly overflow the scaled integer range"
  24398.     dx _ end x - start x.
  24399.     dx < 0 ifTrue:[dx _ dx negated].
  24400.     dy * 32 < dx ifTrue:[
  24401.         OverflowSubdivisions _ OverflowSubdivisions + 1.
  24402.         ^self subdivideAt: 0.5].
  24403.  
  24404.     ^nil! !
  24405.  
  24406. !BalloonBezierSimulation methodsFor: 'computing' stamp: 'ar 10/30/1998 22:13'!
  24407. subdivideAt: parameter
  24408.     "Subdivide the receiver at the given parameter"
  24409.     | both |
  24410.     (parameter <= 0.0 or:[parameter >= 1.0]) ifTrue:[self halt].
  24411.     both _ self computeSplitAt: parameter.
  24412.     "Transcript cr.
  24413.     self quickPrint: self.
  24414.     Transcript space.
  24415.     self quickPrint: both first.
  24416.     Transcript space.
  24417.     self quickPrint: both last.
  24418.     Transcript endEntry."
  24419.     self via: both first via.
  24420.     self end: both first end.
  24421.     ^both last! !
  24422.  
  24423. !BalloonBezierSimulation methodsFor: 'computing' stamp: 'ar 11/11/1998 22:15'!
  24424. subdivideToBeLine
  24425.     "Not a true subdivision.
  24426.     Just return a line representing the receiver and fake me to be of zero height"
  24427.     | line |
  24428.     line _ BalloonLineSimulation new.
  24429.     line start: start.
  24430.     line end: end.
  24431.     "Make me invalid"
  24432.     end _ start.
  24433.     via _ start.
  24434.      ^line! !
  24435.  
  24436. !BalloonBezierSimulation methodsFor: 'computing' stamp: 'ar 10/30/1998 02:24'!
  24437. subdivideToBeMonoton
  24438.     "Subdivide the receiver at it's extreme point"
  24439.     | v1 v2 t other |
  24440.     v1 _ (via - start).
  24441.     v2 _ (end - via).
  24442.     t _ (v1 y / (v2 y - v1 y)) negated asFloat.
  24443.     other _ self subdivideAt: t.
  24444.     self isMonoton ifFalse:[self halt].
  24445.     other isMonoton ifFalse:[self halt].
  24446.     ^other! !
  24447.  
  24448. !BalloonBezierSimulation methodsFor: 'private' stamp: 'ar 10/30/1998 16:37'!
  24449. absoluteSquared8Dot24: value
  24450.     "Compute the squared value of a 8.24 number with 0.0 <= value < 1.0,
  24451.     e.g., compute (value * value) bitShift: -24"
  24452.     | halfWord1 halfWord2 result |
  24453.     (value >= 0 and:[value < 16r1000000]) ifFalse:[^self error:'Value out of range'].
  24454.     halfWord1 _ value bitAnd: 16rFFFF.
  24455.     halfWord2 _ (value bitShift: -16) bitAnd: 255.
  24456.  
  24457.     result _ (halfWord1 * halfWord1) bitShift: -16. "We don't need the lower 16bits at all"
  24458.     result _ result + ((halfWord1 * halfWord2) * 2).
  24459.     result _ result + ((halfWord2 * halfWord2) bitShift: 16).
  24460.     "word1 _ halfWord1 * halfWord1.
  24461.     word2 _ (halfWord2 * halfWord1) + (word1 bitShift: -16).
  24462.     word1 _ word1 bitAnd: 16rFFFF.
  24463.     word2 _ word2 + (halfWord1 * halfWord2).
  24464.     word2 _ word2 + ((halfWord2 * halfWord2) bitShift: 16)."
  24465.  
  24466.     ^result bitShift: -8! !
  24467.  
  24468. !BalloonBezierSimulation methodsFor: 'private' stamp: 'ar 5/25/2000 17:57'!
  24469. debugDraw
  24470.     | entry minY maxY lX lY canvas |
  24471.     entry _ BalloonEdgeData new.
  24472.     canvas _ Display getCanvas.
  24473.     minY _ (start y min: end y) min: via y.
  24474.     maxY _ (start y max: end y) max: via y.
  24475.     entry yValue: minY.
  24476.     self stepToFirstScanLineAt: minY in: entry.
  24477.     lX _ entry xValue.
  24478.     lY _ entry yValue.
  24479.     minY+1 to: maxY do:[:y|
  24480.         self stepToNextScanLineAt: y in: entry.
  24481.         canvas line: lX@lY to: entry xValue @ y width: 2 color: Color black.
  24482.         lX _ entry xValue.
  24483.         lY _ y.
  24484.     ].
  24485. ! !
  24486.  
  24487. !BalloonBezierSimulation methodsFor: 'private' stamp: 'ar 5/25/2000 17:57'!
  24488. debugDraw2
  24489.     | canvas last max t next |
  24490.     canvas _ Display getCanvas.
  24491.     max _ 100.
  24492.     last _ nil.
  24493.     0 to: max do:[:i|
  24494.         t _ i asFloat / max asFloat.
  24495.         next _ self valueAt: t.
  24496.         last ifNotNil:[
  24497.             canvas line: last to: next rounded width: 2 color: Color blue.
  24498.         ].
  24499.         last _ next rounded.
  24500.     ].! !
  24501.  
  24502. !BalloonBezierSimulation methodsFor: 'private' stamp: 'ar 5/25/2000 17:57'!
  24503. debugDrawWide: n
  24504.     | entry minY maxY canvas curve p1 p2 entry2 y |
  24505.     curve _ self class new.
  24506.     curve start: start + (0@n).
  24507.     curve via: via + (0@n).
  24508.     curve end: end + (0@n).
  24509.     entry _ BalloonEdgeData new.
  24510.     entry2 _ BalloonEdgeData new.
  24511.     canvas _ Display getCanvas.
  24512.     minY _ (start y min: end y) min: via y.
  24513.     maxY _ (start y max: end y) max: via y.
  24514.     entry yValue: minY.
  24515.     entry2 yValue: minY + n.
  24516.     self stepToFirstScanLineAt: minY in: entry.
  24517.     curve stepToFirstScanLineAt: minY+n in: entry2.
  24518.     y _ minY.
  24519.     1 to: n do:[:i|
  24520.         y _ y + 1.
  24521.         self stepToNextScanLineAt: y in: entry.
  24522.         p1 _ entry xValue @ y.
  24523.         canvas line: p1 to: p1 + (n@0) width: 1 color: Color black.
  24524.     ].
  24525.     [y < maxY] whileTrue:[
  24526.         y _ y + 1.
  24527.         self stepToNextScanLineAt: y in: entry.
  24528.         p2 _ (entry xValue + n) @ y.
  24529.         curve stepToNextScanLineAt: y in: entry2.
  24530.         p1 _ entry2 xValue @ y.
  24531.         canvas line: p1 to: p2 width: 1 color: Color black.
  24532.     ].
  24533. ! !
  24534.  
  24535. !BalloonBezierSimulation methodsFor: 'private' stamp: 'ar 10/30/1998 00:35'!
  24536. printOn: aStream
  24537.     aStream 
  24538.         nextPutAll: self class name;
  24539.         nextPut:$(;
  24540.         print: start;
  24541.         nextPutAll:' - ';
  24542.         print: via;
  24543.         nextPutAll:' - ';
  24544.         print: end;
  24545.         nextPut:$)! !
  24546.  
  24547. !BalloonBezierSimulation methodsFor: 'private' stamp: 'MPW 1/1/1901 21:55'!
  24548. printOnStream: aStream
  24549.     aStream 
  24550.         print: self class name;
  24551.         print:'(';
  24552.         write: start;
  24553.         print:' - ';
  24554.         write: via;
  24555.         print:' - ';
  24556.         write: end;
  24557.         print:')'.! !
  24558.  
  24559. !BalloonBezierSimulation methodsFor: 'private' stamp: 'ar 10/30/1998 21:56'!
  24560. quickPrint: curve
  24561.     Transcript nextPut:$(;
  24562.         print: curve start;
  24563.         space;
  24564.         print: curve via;
  24565.         space;
  24566.         print: curve end;
  24567.         nextPut:$).! !
  24568.  
  24569. !BalloonBezierSimulation methodsFor: 'private' stamp: 'ar 10/30/1998 22:13'!
  24570. quickPrint: curve first: aBool
  24571.     aBool ifTrue:[Transcript cr].
  24572.     Transcript nextPut:$(;
  24573.         print: curve start;
  24574.         space;
  24575.         print: curve via;
  24576.         space;
  24577.         print: curve end;
  24578.         nextPut:$).
  24579.     Transcript endEntry.! !
  24580.  
  24581. !BalloonBezierSimulation methodsFor: 'private' stamp: 'ar 10/30/1998 03:53'!
  24582. stepToFirst
  24583.     |  startX endX startY endY deltaY fwX1 fwX2 fwY1 fwY2 
  24584.     steps scaledStepSize squaredStepSize |
  24585.     (end y) >= (start y) ifTrue:[
  24586.         startX _ start x.    endX _ end x.
  24587.         startY _ start y.    endY _ end y.
  24588.     ] ifFalse:[
  24589.         startX _ end x.    endX _ start x.
  24590.         startY _ end y.    endY _ start y.
  24591.     ].
  24592.  
  24593.     deltaY _ endY - startY.
  24594.  
  24595.     "Quickly check if the line is visible at all"
  24596.     (deltaY = 0) ifTrue:[^self].
  24597.  
  24598.     fwX1 _ (startX + endX - (2 * via x)) asFloat.
  24599.     fwX2 _ (via x - startX * 2) asFloat.
  24600.     fwY1 _ (startY + endY - (2 * via y)) asFloat.
  24601.     fwY2 _ ((via y - startY) * 2) asFloat.
  24602.     steps _ deltaY asInteger * 2.
  24603.     scaledStepSize _ 1.0 / steps asFloat.
  24604.     squaredStepSize _ scaledStepSize * scaledStepSize.
  24605.     fwDx _ fwX2 * scaledStepSize.
  24606.     fwDDx _ 2.0 * fwX1 * squaredStepSize.
  24607.     fwDy _ fwY2 * scaledStepSize.
  24608.     fwDDy _ 2.0 * fwY1 * squaredStepSize.
  24609.     fwDx _ fwDx + (fwDDx * 0.5).
  24610.     fwDy _ fwDy + (fwDDy * 0.5).
  24611.  
  24612.     lastX _ startX asFloat.
  24613.     lastY _ startY asFloat.
  24614. ! !
  24615.  
  24616. !BalloonBezierSimulation methodsFor: 'private' stamp: 'ar 10/30/1998 03:50'!
  24617. stepToFirstInt
  24618.     "Scaled integer version of forward differencing"
  24619.     |  startX endX startY endY deltaY fwX1 fwX2 fwY1 fwY2 
  24620.      scaledStepSize squaredStepSize |
  24621.     self halt.
  24622.     (end y) >= (start y) ifTrue:[
  24623.         startX _ start x.    endX _ end x.
  24624.         startY _ start y.    endY _ end y.
  24625.     ] ifFalse:[
  24626.         startX _ end x.    endX _ start x.
  24627.         startY _ end y.    endY _ start y.
  24628.     ].
  24629.  
  24630.     deltaY _ endY - startY.
  24631.  
  24632.     "Quickly check if the line is visible at all"
  24633.     (deltaY = 0) ifTrue:[^nil].
  24634.  
  24635.     fwX1 _ (startX + endX - (2 * via x)).
  24636.     fwX2 _ (via x - startX * 2).
  24637.     fwY1 _ (startY + endY - (2 * via y)).
  24638.     fwY2 _ ((via y - startY) * 2).
  24639.     maxSteps _ deltaY asInteger * 2.
  24640.     scaledStepSize _ 16r1000000 // maxSteps.
  24641.     "@@: Okay, we need some fancy 64bit multiplication here"
  24642.     squaredStepSize _ (scaledStepSize * scaledStepSize) bitShift: -24.
  24643.     fwDx _ fwX2 * scaledStepSize.
  24644.     fwDDx _ 2 * fwX1 * squaredStepSize.
  24645.     fwDy _ fwY2 * scaledStepSize.
  24646.     fwDDy _ 2 * fwY1 * squaredStepSize.
  24647.     fwDx _ fwDx + (fwDDx // 2).
  24648.     fwDy _ fwDy + (fwDDy // 2).
  24649.  
  24650.     self validateIntegerRange.
  24651.  
  24652.     lastX _ startX * 256.
  24653.     lastY _ startY * 256.
  24654. ! !
  24655.  
  24656. !BalloonBezierSimulation methodsFor: 'private' stamp: 'ar 10/30/1998 00:26'!
  24657. stepToNext
  24658.         lastX _ lastX + fwDx.
  24659.         lastY _ lastY + fwDy.
  24660.         fwDx _ fwDx + fwDDx.
  24661.         fwDy _ fwDy + fwDDy.! !
  24662.  
  24663. !BalloonBezierSimulation methodsFor: 'private' stamp: 'ar 10/30/1998 04:01'!
  24664. stepToNextInt
  24665.     "Scaled integer version of forward differencing"
  24666.     self halt.
  24667.     (maxSteps >= 0) ifTrue:[
  24668.         self validateIntegerRange.
  24669.         lastX _ lastX + ((fwDx + 16r8000) // 16r10000).
  24670.         lastY _ lastY + ((fwDy + 16r8000) // 16r10000).
  24671.         fwDx _ fwDx + fwDDx.
  24672.         fwDy _ fwDy + fwDDy.
  24673.         maxSteps _ maxSteps - 1.
  24674.     ].! !
  24675.  
  24676. !BalloonBezierSimulation methodsFor: 'private' stamp: 'ar 10/30/1998 03:27'!
  24677. validateIntegerRange
  24678.     fwDx class == SmallInteger ifFalse:[self halt].
  24679.     fwDy class == SmallInteger ifFalse:[self halt].
  24680.     fwDDx class == SmallInteger ifFalse:[self halt].
  24681.     fwDDy class == SmallInteger ifFalse:[self halt].
  24682. ! !
  24683.  
  24684. !BalloonBezierSimulation methodsFor: 'private' stamp: 'ar 10/29/1998 21:26'!
  24685. valueAt: parameter
  24686.     "Return the point at the value parameter:
  24687.         p(t) =    (1-t)^2 * p1 + 
  24688.                 2*t*(1-t) * p2 + 
  24689.                 t^2 * p3.
  24690.     "
  24691.     | t1 t2 t3 |
  24692.     t1 _ (1.0 - parameter) squared.
  24693.     t2 _ 2 * parameter * (1.0 - parameter).
  24694.     t3 _ parameter squared.
  24695.     ^(start * t1) + (via * t2) + (end * t3)! !
  24696.  
  24697. !BalloonBezierSimulation class methodsFor: 'class initialization' stamp: 'ar 10/30/1998 03:04'!
  24698. initialize
  24699.     "GraphicsBezierSimulation initialize"
  24700.     HeightSubdivisions _ 0.
  24701.     LineConversions _ 0.
  24702.     MonotonSubdivisions _ 0.
  24703.     OverflowSubdivisions _ 0.! !
  24704.  
  24705. !BalloonBuffer methodsFor: 'accessing' stamp: 'ar 10/26/1998 21:12'!
  24706. at: index
  24707.     "For simulation only"
  24708.     | word |
  24709.     word _ self basicAt: index.
  24710.     word < 16r3FFFFFFF ifTrue:[^word]. "Avoid LargeInteger computations"
  24711.     ^word >= 16r80000000    "Negative?!!"
  24712.         ifTrue:["word - 16r100000000"
  24713.                 (word bitInvert32 + 1) negated]
  24714.         ifFalse:[word]! !
  24715.  
  24716. !BalloonBuffer methodsFor: 'accessing' stamp: 'ar 10/26/1998 21:12'!
  24717. at: index put: anInteger
  24718.     "For simulation only"
  24719.     | word |
  24720.     anInteger < 0
  24721.         ifTrue:["word _ 16r100000000 + anInteger"
  24722.                 word _ (anInteger + 1) negated bitInvert32]
  24723.         ifFalse:[word _ anInteger].
  24724.     self  basicAt: index put: word.
  24725.     ^anInteger! !
  24726.  
  24727. !BalloonBuffer methodsFor: 'accessing' stamp: 'ar 2/4/1999 17:04'!
  24728. floatAt: index
  24729.     "For simulation only"
  24730.     <primitive: 'primitiveFloatArrayAt'>
  24731.     ^Float fromIEEE32Bit: (self basicAt: index)! !
  24732.  
  24733. !BalloonBuffer methodsFor: 'accessing' stamp: 'ar 2/4/1999 17:06'!
  24734. floatAt: index put: value
  24735.     "For simulation only"
  24736.     <primitive: 'primitiveFloatArrayAtPut'>
  24737.     value isFloat 
  24738.         ifTrue:[self basicAt: index put: value asIEEE32BitWord]
  24739.         ifFalse:[self at: index put: value asFloat].
  24740.     ^value! !
  24741.  
  24742. !BalloonBuffer class methodsFor: 'instance creation' stamp: 'ar 10/26/1998 21:11'!
  24743. mew: n
  24744.     ^self new: (n max: 256)! !
  24745.  
  24746. !BalloonBuffer class methodsFor: 'instance creation' stamp: 'ar 10/26/1998 21:11'!
  24747. new
  24748.     ^self new: 256.! !
  24749.  
  24750. !BalloonCanvas methodsFor: 'initialize' stamp: 'ar 11/24/1998 15:28'!
  24751. flush
  24752.     "Force all pending primitives onscreen"
  24753.     engine ifNotNil:[engine flush].! !
  24754.  
  24755. !BalloonCanvas methodsFor: 'initialize' stamp: 'ar 12/30/1998 10:54'!
  24756. initialize
  24757.     aaLevel _ 1.
  24758.     deferred _ false.! !
  24759.  
  24760. !BalloonCanvas methodsFor: 'initialize' stamp: 'ar 11/11/1998 20:25'!
  24761. resetEngine
  24762.     engine _ nil.! !
  24763.  
  24764. !BalloonCanvas methodsFor: 'accessing' stamp: 'ar 11/13/1998 01:02'!
  24765. aaLevel
  24766.     ^aaLevel! !
  24767.  
  24768. !BalloonCanvas methodsFor: 'accessing' stamp: 'ar 12/30/1998 10:53'!
  24769. aaLevel: newLevel
  24770.     "Only allow changes to aaLevel if we're working on >= 8 bit forms"
  24771.     form depth >= 8 ifFalse:[^self].
  24772.     aaLevel = newLevel ifTrue:[^self].
  24773.     self flush.    "In case there are pending primitives in the engine"
  24774.     aaLevel _ newLevel.
  24775.     engine ifNotNil:[engine aaLevel: aaLevel].! !
  24776.  
  24777. !BalloonCanvas methodsFor: 'accessing' stamp: 'ar 12/30/1998 10:54'!
  24778. deferred
  24779.     ^deferred! !
  24780.  
  24781. !BalloonCanvas methodsFor: 'accessing' stamp: 'ar 12/30/1998 10:55'!
  24782. deferred: aBoolean
  24783.     deferred == aBoolean ifTrue:[^self].
  24784.     self flush. "Force pending prims on screen"
  24785.     deferred _ aBoolean.
  24786.     engine ifNotNil:[engine deferred: aBoolean].! !
  24787.  
  24788. !BalloonCanvas methodsFor: 'accessing' stamp: 'ar 12/30/1998 10:55'!
  24789. ensuredEngine
  24790.     engine ifNil:[
  24791.         true
  24792.             ifTrue:[engine _ BalloonEngine new]
  24793.             ifFalse:[engine _ BalloonDebugEngine new].
  24794.         engine aaLevel: aaLevel.
  24795.         engine bitBlt: port.
  24796.         engine destOffset: origin.
  24797.         engine clipRect: clipRect.
  24798.         engine deferred: deferred.
  24799.         engine].
  24800.     engine colorTransform: colorTransform.
  24801.     engine edgeTransform: transform.
  24802.     ^engine! !
  24803.  
  24804. !BalloonCanvas methodsFor: 'testing' stamp: 'ar 11/13/1998 13:19'!
  24805. isBalloonCanvas
  24806.     ^true! !
  24807.  
  24808. !BalloonCanvas methodsFor: 'testing' stamp: 'ar 11/12/1998 01:07'!
  24809. isVisible: aRectangle
  24810.     ^transform 
  24811.         ifNil:[super isVisible: aRectangle]
  24812.         ifNotNil:[super isVisible: (transform localBoundsToGlobal: aRectangle)]! !
  24813.  
  24814. !BalloonCanvas methodsFor: 'copying' stamp: 'ar 11/24/1998 22:33'!
  24815. copy
  24816.     self flush.
  24817.     ^super copy resetEngine! !
  24818.  
  24819. !BalloonCanvas methodsFor: 'drawing' stamp: 'ar 2/9/1999 05:40'!
  24820. fillColor: c
  24821.     "Note: This always fills, even if the color is transparent."
  24822.     "Note2: To achieve the above we must make sure that c is NOT transparent"
  24823.     self frameAndFillRectangle: form boundingBox 
  24824.         fillColor: (c alpha: 1.0)
  24825.         borderWidth: 0
  24826.         borderColor: nil! !
  24827.  
  24828. !BalloonCanvas methodsFor: 'drawing' stamp: 'ar 2/9/1999 05:51'!
  24829. fillOval: r color: c borderWidth: borderWidth borderColor: borderColor
  24830.     "Draw a filled and outlined oval"
  24831.     "Note: The optimization test below should actually read:
  24832.         self ifNoTransformWithIn: (r insetBy: borderWidth // 2)
  24833.     but since borderWidth is assumed to be very small related to r we don't check it."
  24834.  
  24835.     (self ifNoTransformWithIn: r)
  24836.         ifTrue:[^super fillOval: r color: c borderWidth: borderWidth borderColor: borderColor].
  24837.  
  24838.     ^self drawOval: (r insetBy: borderWidth // 2) 
  24839.             color: c 
  24840.             borderWidth: borderWidth 
  24841.             borderColor: borderColor! !
  24842.  
  24843. !BalloonCanvas methodsFor: 'drawing' stamp: 'ar 2/9/1999 05:40'!
  24844. fillRectangle: r color: c
  24845.     "Fill the rectangle with the given color"
  24846.     ^self frameAndFillRectangle: r
  24847.             fillColor: c
  24848.             borderWidth: 0
  24849.             borderColor: nil! !
  24850.  
  24851. !BalloonCanvas methodsFor: 'drawing' stamp: 'ar 2/9/1999 06:26'!
  24852. frameAndFillRectangle: r fillColor: c borderWidth: borderWidth borderColor: borderColor
  24853.     "Draw a filled and outlined rectangle"
  24854.     "Note: The optimization test below should actually read:
  24855.         self ifNoTransformWithIn: (r insetBy: borderWidth // 2)
  24856.     but since borderWidth is assumed to be very small related to r we don't check it."
  24857.  
  24858.     (self ifNoTransformWithIn: r)
  24859.         ifTrue:[^super frameAndFillRectangle: r fillColor: c borderWidth: borderWidth borderColor: borderColor].
  24860.  
  24861.     ^self drawRectangle: (r insetBy: borderWidth // 2) 
  24862.             color: c 
  24863.             borderWidth: borderWidth 
  24864.             borderColor: borderColor! !
  24865.  
  24866. !BalloonCanvas methodsFor: 'drawing' stamp: 'ar 2/9/1999 05:52'!
  24867. frameAndFillRectangle: r fillColor: fillColor borderWidth: borderWidth topLeftColor: topLeftColor bottomRightColor: bottomRightColor
  24868.     "Draw a beveled or raised rectangle"
  24869.     | bw |
  24870.  
  24871.     "Note: The optimization test below should actually read:
  24872.         self ifNoTransformWithIn: (r insetBy: borderWidth // 2)
  24873.     but since borderWidth is assumed to be very small related to r we don't check it."
  24874.  
  24875.     (self ifNoTransformWithIn: r)
  24876.         ifTrue:[^super frameAndFillRectangle: r fillColor: fillColor borderWidth: borderWidth topLeftColor: topLeftColor bottomRightColor: bottomRightColor].
  24877.  
  24878.     "Fill rectangle and draw top and left border"
  24879.     bw _ borderWidth // 2.
  24880.     self drawRectangle: (r insetBy: bw)
  24881.         color: fillColor
  24882.         borderWidth: borderWidth
  24883.         borderColor: topLeftColor.
  24884.     "Now draw bottom right border."
  24885.     self drawPolygon: (Array with: r topRight + (bw negated@bw) 
  24886.                             with: r bottomRight - bw asPoint
  24887.                             with: r bottomLeft + (bw@bw negated))
  24888.         color: nil
  24889.         borderWidth: borderWidth
  24890.         borderColor: bottomRightColor.! !
  24891.  
  24892. !BalloonCanvas methodsFor: 'drawing' stamp: 'ar 2/9/1999 05:41'!
  24893. frameRectangle: r width: w color: c
  24894.     "Draw a frame around the given rectangle"
  24895.     ^self frameAndFillRectangle: r
  24896.             fillColor: nil
  24897.             borderWidth: w
  24898.             borderColor: c! !
  24899.  
  24900. !BalloonCanvas methodsFor: 'drawing' stamp: 'ar 2/12/1999 17:45'!
  24901. line: pt1 to: pt2 width: w color: c
  24902.     "Draw a line from pt1 to: pt2"
  24903.     (self ifNoTransformWithIn:(pt1 rect: pt2))
  24904.         ifTrue:[^super line: pt1 to: pt2 width: w color: c].
  24905.     ^self drawPolygon: (Array with: pt1 with: pt2)
  24906.         color: c
  24907.         borderWidth: w
  24908.         borderColor: c! !
  24909.  
  24910. !BalloonCanvas methodsFor: 'drawing' stamp: 'ar 11/11/1998 19:39'!
  24911. point: pt color: c
  24912.     "Is there any use for this?"
  24913.     | myPt |
  24914.     transform 
  24915.         ifNil:[myPt _ pt]
  24916.         ifNotNil:[myPt _ transform localPointToGlobal: pt].
  24917.     ^super point: myPt color: c! !
  24918.  
  24919. !BalloonCanvas methodsFor: 'balloon drawing' stamp: 'DSM 10/15/1999 15:14'!
  24920. drawBezier3Shape: vertices color: c borderWidth: borderWidth borderColor:
  24921. borderColor
  24922.     self drawBezierShape: (Bezier3Segment convertBezier3ToBezier2:
  24923. vertices) color: c borderWidth: borderWidth borderColor: borderColor! !
  24924.  
  24925. !BalloonCanvas methodsFor: 'balloon drawing' stamp: 'ar 2/17/2000 00:25'!
  24926. drawBezierShape: vertices color: c borderWidth: borderWidth borderColor: borderColor
  24927.     "Draw a boundary shape that is defined by a list of vertices.
  24928.     Each three subsequent vertices define a quadratic bezier segment.
  24929.     For lines, the control point should be set to either the start or the end
  24930.     of the bezier curve."
  24931.     | fillC borderC |
  24932.     fillC _ self shadowColor ifNil:[c].
  24933.     borderC _ self shadowColor ifNil:[borderColor].
  24934.     self ensuredEngine
  24935.         drawBezierShape: vertices
  24936.         fill: fillC
  24937.         borderWidth: borderWidth
  24938.         borderColor: borderC
  24939.         transform: transform.! !
  24940.  
  24941. !BalloonCanvas methodsFor: 'balloon drawing' stamp: 'ar 11/24/1998 15:16'!
  24942. drawCompressedShape: compressedShape
  24943.     "Draw a compressed shape"
  24944.     self ensuredEngine
  24945.         drawCompressedShape: compressedShape
  24946.         transform: transform.! !
  24947.  
  24948. !BalloonCanvas methodsFor: 'balloon drawing' stamp: 'DSM 10/15/1999 15:18'!
  24949. drawGeneralBezier3Shape: contours color: c borderWidth: borderWidth
  24950. borderColor: borderColor
  24951.     | b2 |
  24952.     b2 _ contours collect: [:b3 | Bezier3Segment
  24953. convertBezier3ToBezier2: b3 ].
  24954.     self drawGeneralBezierShape: b2 color: c borderWidth: borderWidth
  24955. borderColor: borderColor! !
  24956.  
  24957. !BalloonCanvas methodsFor: 'balloon drawing' stamp: 'ar 2/17/2000 00:24'!
  24958. drawGeneralBezierShape: contours color: c borderWidth: borderWidth borderColor: borderColor
  24959.     "Draw a general boundary shape (e.g., possibly containing holes)"
  24960.     | fillC borderC |
  24961.     fillC _ self shadowColor ifNil:[c].
  24962.     borderC _ self shadowColor ifNil:[borderColor].
  24963.     self ensuredEngine
  24964.         drawGeneralBezierShape: contours
  24965.         fill: fillC
  24966.         borderWidth: borderWidth
  24967.         borderColor: borderC
  24968.         transform: transform.! !
  24969.  
  24970. !BalloonCanvas methodsFor: 'balloon drawing' stamp: 'ar 2/17/2000 00:24'!
  24971. drawGeneralPolygon: contours color: c borderWidth: borderWidth borderColor: borderColor
  24972.     "Draw a general polygon (e.g., a polygon that can contain holes)"
  24973.     | fillC borderC |
  24974.     fillC _ self shadowColor ifNil:[c].
  24975.     borderC _ self shadowColor ifNil:[borderColor].
  24976.     self ensuredEngine
  24977.         drawGeneralPolygon: contours
  24978.         fill: fillC
  24979.         borderWidth: borderWidth
  24980.         borderColor: borderC
  24981.         transform: transform.! !
  24982.  
  24983. !BalloonCanvas methodsFor: 'balloon drawing' stamp: 'ar 2/17/2000 00:24'!
  24984. drawOval: r color: c borderWidth: borderWidth borderColor: borderColor
  24985.     "Draw the oval defined by the given rectangle"
  24986.     | fillC borderC |
  24987.     fillC _ self shadowColor ifNil:[c].
  24988.     borderC _ self shadowColor ifNil:[borderColor].
  24989.     self ensuredEngine
  24990.         drawOval: r
  24991.         fill: fillC
  24992.         borderWidth: borderWidth
  24993.         borderColor: borderC
  24994.         transform: transform.! !
  24995.  
  24996. !BalloonCanvas methodsFor: 'balloon drawing' stamp: 'ar 2/17/2000 00:24'!
  24997. drawRectangle: r color: c borderWidth: borderWidth borderColor: borderColor
  24998.     "Draw a rectangle"
  24999.     | fillC borderC |
  25000.     fillC _ self shadowColor ifNil:[c].
  25001.     borderC _ self shadowColor ifNil:[borderColor].
  25002.     self ensuredEngine
  25003.         drawRectangle: r
  25004.         fill: fillC
  25005.         borderWidth: borderWidth
  25006.         borderColor: borderC
  25007.         transform: transform.! !
  25008.  
  25009. !BalloonCanvas methodsFor: 'balloon drawing' stamp: 'ar 5/28/2000 12:23'!
  25010. render: anObject
  25011.     | b3d |
  25012.     b3d _ (B3DRenderEngine defaultForPlatformOn: form).
  25013.     "Install the viewport offset"
  25014.     b3d viewportOffset: origin.
  25015.     "Install the clipping rectangle for the target form"
  25016.     b3d clipRect: clipRect.
  25017.     anObject renderOn: b3d.
  25018.     b3d flush.! !
  25019.  
  25020. !BalloonCanvas methodsFor: 'TODO' stamp: 'ar 2/9/1999 05:46'!
  25021. line: point1 to: point2 brushForm: brush
  25022.     "Who's gonna use this?"
  25023.     | pt1 pt2 |
  25024.     self flush. "Sorry, but necessary..."
  25025.     transform 
  25026.         ifNil:[pt1 _ point1. pt2 _ point2]
  25027.         ifNotNil:[pt1 _ transform localPointToGlobal: point1.
  25028.                 pt2 _ transform localPointToGlobal: point2].
  25029.     ^super line: pt1 to: pt2 brushForm: brush! !
  25030.  
  25031. !BalloonCanvas methodsFor: 'TODO' stamp: 'ar 2/9/1999 05:46'!
  25032. paragraph: para bounds: bounds color: c
  25033.     (self ifNoTransformWithIn: bounds)
  25034.         ifTrue:[^super paragraph: para bounds: bounds color: c].! !
  25035.  
  25036. !BalloonCanvas methodsFor: 'TODO' stamp: 'ar 2/9/1999 05:38'!
  25037. text: s bounds: boundsRect font: fontOrNil color: c
  25038.     (self ifNoTransformWithIn: boundsRect)
  25039.         ifTrue:[^super text: s bounds: boundsRect font: fontOrNil color: c]! !
  25040.  
  25041. !BalloonCanvas methodsFor: 'transforming' stamp: 'ar 11/24/1998 14:45'!
  25042. colorTransformBy: aColorTransform
  25043.     aColorTransform ifNil:[^self].
  25044.     colorTransform 
  25045.         ifNil:[colorTransform _ aColorTransform]
  25046.         ifNotNil:[colorTransform _ colorTransform composedWithLocal: aColorTransform]! !
  25047.  
  25048. !BalloonCanvas methodsFor: 'transforming' stamp: 'ar 12/30/1998 10:47'!
  25049. preserveStateDuring: aBlock
  25050.     | state result |
  25051.     state _ BalloonState new.
  25052.     state transform: transform.
  25053.     state colorTransform: colorTransform.
  25054.     state aaLevel: self aaLevel.
  25055.     result _ aBlock value: self.
  25056.     transform _ state transform.
  25057.     colorTransform _ state colorTransform.
  25058.     self aaLevel: state aaLevel.
  25059.     ^result! !
  25060.  
  25061. !BalloonCanvas methodsFor: 'transforming' stamp: 'ar 11/12/1998 00:32'!
  25062. transformBy: aTransform
  25063.     aTransform ifNil:[^self].
  25064.     transform 
  25065.         ifNil:[transform _ aTransform]
  25066.         ifNotNil:[transform _ transform composedWithLocal: aTransform]! !
  25067.  
  25068. !BalloonCanvas methodsFor: 'transforming' stamp: 'ar 5/29/1999 08:59'!
  25069. transformBy: aDisplayTransform during: aBlock
  25070.     | myTransform result |
  25071.     myTransform _ transform.
  25072.     self transformBy: aDisplayTransform.
  25073.     result _ aBlock value: self.
  25074.     transform _ myTransform.
  25075.     ^result! !
  25076.  
  25077. !BalloonCanvas methodsFor: 'private' stamp: 'ar 2/9/1999 06:29'!
  25078. ifNoTransformWithIn: box
  25079.     "Return true if the current transformation does not affect the given bounding box"
  25080.     | delta |
  25081.     "false ifFalse:[^false]."
  25082.     transform isNil ifTrue:[^true].
  25083.     delta _ (transform localPointToGlobal: box origin) - box origin.
  25084.     ^(transform localPointToGlobal: box corner) - box corner = delta! !
  25085.  
  25086. !BalloonCanvas methodsFor: 'private' stamp: 'ar 5/28/2000 12:12'!
  25087. image: aForm at: aPoint sourceRect: sourceRect rule: rule
  25088.     | warp dstRect srcQuad dstOffset center |
  25089.     (self ifNoTransformWithIn: sourceRect) & false
  25090.         ifTrue:[^super image: aForm at: aPoint sourceRect: sourceRect rule: rule].
  25091.     dstRect _ (transform localBoundsToGlobal: (aForm boundingBox translateBy: aPoint)).
  25092.     dstOffset _ 0@0. "dstRect origin."
  25093.     "dstRect _ 0@0 corner: dstRect extent."
  25094.     center _ 0@0."transform globalPointToLocal: dstRect origin."
  25095.     srcQuad _ transform globalPointsToLocal: (dstRect innerCorners).
  25096.     srcQuad _ srcQuad collect:[:pt| pt - aPoint].
  25097.     warp _ (WarpBlt current toForm: Display)
  25098.             sourceForm: aForm;
  25099.             cellSize: 2;  "installs a new colormap if cellSize > 1"
  25100.             combinationRule: Form over.
  25101.     warp copyQuad: srcQuad toRect: (dstRect translateBy: dstOffset).
  25102.  
  25103.     self frameRectangle: (aForm boundingBox translateBy: aPoint) color: Color green.
  25104.  
  25105.     "... TODO ... create a bitmap fill style from the form and use it for a simple rectangle."! !
  25106.  
  25107. !BalloonCanvas methodsFor: 'converting' stamp: 'ar 11/11/1998 22:57'!
  25108. asBalloonCanvas
  25109.     ^self! !
  25110.  
  25111. !BalloonCanvas methodsFor: 'drawing-rectangles' stamp: 'ar 6/18/1999 08:48'!
  25112. fillRectangle: aRectangle fillStyle: aFillStyle
  25113.     "Fill the given rectangle."
  25114.     ^self drawRectangle: aRectangle
  25115.             color: aFillStyle "@@: Name confusion!!!!!!"
  25116.             borderWidth: 0
  25117.             borderColor: nil
  25118. ! !
  25119.  
  25120. !BalloonCanvas methodsFor: 'drawing-ovals' stamp: 'ar 6/18/1999 08:50'!
  25121. fillOval: aRectangle fillStyle: aFillStyle borderWidth: bw borderColor: bc
  25122.     "Fill the given rectangle."
  25123.     ^self drawOval: (aRectangle insetBy: bw // 2)
  25124.             color: aFillStyle "@@: Name confusion!!!!!!"
  25125.             borderWidth: bw
  25126.             borderColor: bc
  25127. ! !
  25128.  
  25129. !BalloonCanvas methodsFor: 'drawing-polygons' stamp: 'ar 6/18/1999 09:00'!
  25130. drawPolygon: vertices color: aColor borderWidth: bw borderColor: bc
  25131.     "Generalize for the BalloonCanvas"
  25132.     ^self drawPolygon: vertices fillStyle: aColor borderWidth: bw borderColor: bc! !
  25133.  
  25134. !BalloonCanvas methodsFor: 'drawing-polygons' stamp: 'ar 2/17/2000 00:25'!
  25135. drawPolygon: vertices fillStyle: aFillStyle borderWidth: borderWidth borderColor: borderColor
  25136.     "Draw a simple polygon defined by the list of vertices."
  25137.     | fillC borderC |
  25138.     fillC _ self shadowColor ifNil:[aFillStyle].
  25139.     borderC _ self shadowColor ifNil:[borderColor].
  25140.     self ensuredEngine
  25141.         drawPolygon: (vertices copyWith: vertices first)
  25142.         fill: fillC
  25143.         borderWidth: borderWidth
  25144.         borderColor: borderC
  25145.         transform: transform.! !
  25146.  
  25147. !BalloonCanvas class methodsFor: 'instance creation' stamp: 'ar 11/11/1998 19:14'!
  25148. new
  25149.     ^super new initialize! !
  25150.  
  25151. !BalloonDebugEngine methodsFor: 'initialize' stamp: 'ar 11/25/1998 22:30'!
  25152. initialize
  25153.     super initialize.
  25154.     deferred _ true.! !
  25155.  
  25156. !BalloonDebugEngine methodsFor: 'initialize' stamp: 'ar 11/25/1998 01:45'!
  25157. reset
  25158.     workBuffer _ BalloonBuffer new: 400000.
  25159.     super reset.! !
  25160.  
  25161. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:04'!
  25162. primClipRectInto: rect
  25163.     ^BalloonEnginePlugin doPrimitive:'gePrimitiveGetClipRect'! !
  25164.  
  25165. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/25/1998 22:29'!
  25166. primFlushNeeded
  25167.     "Return true if there are no more entries in AET and GET and the last scan line has been displayed"
  25168.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveNeedsFlush'! !
  25169.  
  25170. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:04'!
  25171. primGetAALevel
  25172.     "Set the AA level"
  25173.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetAALevel'! !
  25174.  
  25175. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:04'!
  25176. primGetBezierStats: statsArray
  25177.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetBezierStats'! !
  25178.  
  25179. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:04'!
  25180. primGetClipRect: rect
  25181.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetClipRect'! !
  25182.  
  25183. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:05'!
  25184. primGetCounts: statsArray
  25185.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetCounts'! !
  25186.  
  25187. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:55'!
  25188. primGetDepth
  25189.     "Set the AA level"
  25190.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetDepth'! !
  25191.  
  25192. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:05'!
  25193. primGetFailureReason
  25194.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetFailureReason'! !
  25195.  
  25196. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:05'!
  25197. primGetOffset
  25198.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetOffset'! !
  25199.  
  25200. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:05'!
  25201. primGetTimes: statsArray
  25202.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetTimes'! !
  25203.  
  25204. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/25/1998 22:20'!
  25205. primNeedsFlush
  25206.     "Return true if there are no more entries in AET and GET and the last scan line has been displayed"
  25207.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveNeedsFlush'! !
  25208.  
  25209. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:05'!
  25210. primSetAALevel: level
  25211.     "Set the AA level"
  25212.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveSetAALevel'! !
  25213.  
  25214. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:05'!
  25215. primSetClipRect: rect
  25216.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveSetClipRect'! !
  25217.  
  25218. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:06'!
  25219. primSetColorTransform: transform
  25220.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveSetColorTransform'! !
  25221.  
  25222. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:06'!
  25223. primSetDepth: depth
  25224.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveSetDepth'! !
  25225.  
  25226. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:06'!
  25227. primSetEdgeTransform: transform
  25228.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveSetEdgeTransform'! !
  25229.  
  25230. !BalloonDebugEngine methodsFor: 'primitives-access' stamp: 'ar 11/24/1998 21:06'!
  25231. primSetOffset: point
  25232.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveSetOffset'! !
  25233.  
  25234. !BalloonDebugEngine methodsFor: 'primitives-adding' stamp: 'ar 11/24/1998 21:11'!
  25235. primAddBezierFrom: start to: end via: via leftFillIndex: leftFillIndex rightFillIndex: rightFillIndex
  25236.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveAddBezier'! !
  25237.  
  25238. !BalloonDebugEngine methodsFor: 'primitives-adding' stamp: 'ar 11/24/1998 21:01'!
  25239. primAddBezierShape: points segments: nSegments fill: fillStyle lineWidth: lineWidth lineFill: lineFill
  25240.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveAddBezierShape'! !
  25241.  
  25242. !BalloonDebugEngine methodsFor: 'primitives-adding' stamp: 'ar 11/27/1998 14:27'!
  25243. primAddBitmapFill: form colormap: cmap tile: tileFlag from: origin along: direction normal: normal xIndex: xIndex
  25244.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveAddBitmapFill'! !
  25245.  
  25246. !BalloonDebugEngine methodsFor: 'primitives-adding' stamp: 'ar 11/24/1998 21:01'!
  25247. primAddCompressedShape: points segments: nSegments leftFills: leftFills rightFills: rightFills lineWidths: lineWidths lineFills: lineFills fillIndexList: fillIndexList
  25248.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveAddCompressedShape'! !
  25249.  
  25250. !BalloonDebugEngine methodsFor: 'primitives-adding' stamp: 'ar 11/24/1998 21:02'!
  25251. primAddExternalEdge: index initialX: initialX initialY: initialY initialZ: initialZ leftFillIndex: leftFillIndex rightFillIndex: rightFillIndex
  25252.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveRegisterExternalEdge'! !
  25253.  
  25254. !BalloonDebugEngine methodsFor: 'primitives-adding' stamp: 'ar 11/24/1998 21:02'!
  25255. primAddExternalFill: index
  25256.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveRegisterExternalFill'! !
  25257.  
  25258. !BalloonDebugEngine methodsFor: 'primitives-adding' stamp: 'ar 11/24/1998 21:02'!
  25259. primAddGradientFill: colorRamp from: origin along: direction normal: normal radial: isRadial
  25260.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveAddGradientFill'! !
  25261.  
  25262. !BalloonDebugEngine methodsFor: 'primitives-adding' stamp: 'ar 11/24/1998 21:16'!
  25263. primAddLineFrom: start to: end leftFillIndex: leftFillIndex rightFillIndex: rightFillIndex
  25264.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveAddLine'! !
  25265.  
  25266. !BalloonDebugEngine methodsFor: 'primitives-adding' stamp: 'ar 11/24/1998 21:03'!
  25267. primAddOvalFrom: start to: end fillIndex: fillIndex borderWidth: width borderColor: pixelValue32
  25268.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveAddOval'! !
  25269.  
  25270. !BalloonDebugEngine methodsFor: 'primitives-adding' stamp: 'ar 11/24/1998 21:03'!
  25271. primAddPolygon: points segments: nSegments fill: fillStyle lineWidth: lineWidth lineFill: lineFill
  25272.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveAddPolygon'! !
  25273.  
  25274. !BalloonDebugEngine methodsFor: 'primitives-adding' stamp: 'ar 11/24/1998 21:20'!
  25275. primAddRectFrom: start to: end fillIndex: fillIndex borderWidth: width borderColor: pixelValue32
  25276.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveAddRect'! !
  25277.  
  25278. !BalloonDebugEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/24/1998 20:59'!
  25279. primAddActiveEdgeTableEntryFrom: edgeEntry
  25280.     "Add edge entry to the AET."
  25281.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveAddActiveEdgeEntry'! !
  25282.  
  25283. !BalloonDebugEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/24/1998 20:59'!
  25284. primChangeActiveEdgeTableEntryFrom: edgeEntry
  25285.     "Change the entry in the active edge table from edgeEntry"
  25286.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveChangedActiveEdgeEntry'! !
  25287.  
  25288. !BalloonDebugEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/24/1998 20:59'!
  25289. primDisplaySpanBuffer
  25290.     "Display the current scan line if necessary"
  25291.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveDisplaySpanBuffer'! !
  25292.  
  25293. !BalloonDebugEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/24/1998 20:59'!
  25294. primFinishedProcessing
  25295.     "Return true if there are no more entries in AET and GET and the last scan line has been displayed"
  25296.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveFinishedProcessing'! !
  25297.  
  25298. !BalloonDebugEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/24/1998 21:00'!
  25299. primInitializeProcessing
  25300.     "Initialize processing in the GE.
  25301.     Create the active edge table and sort it."
  25302.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveInitializeProcessing'! !
  25303.  
  25304. !BalloonDebugEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/24/1998 21:00'!
  25305. primMergeFill: fillBitmap from: fill
  25306.     "Merge the filled bitmap into the current output buffer."
  25307.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveMergeFillFrom'! !
  25308.  
  25309. !BalloonDebugEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/24/1998 21:00'!
  25310. primNextActiveEdgeEntryInto: edgeEntry
  25311.     "Store the next entry of the AET at the current y-value in edgeEntry.
  25312.     Return false if there is no entry, true otherwise."
  25313.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveNextActiveEdgeEntry'! !
  25314.  
  25315. !BalloonDebugEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/24/1998 21:00'!
  25316. primNextFillEntryInto: fillEntry
  25317.     "Store the next fill entry of the active edge table in fillEntry.
  25318.     Return false if there is no such entry, true otherwise"
  25319.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveNextFillEntry'! !
  25320.  
  25321. !BalloonDebugEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/24/1998 21:00'!
  25322. primNextGlobalEdgeEntryInto: edgeEntry
  25323.     "Store the next entry of the GET at the current y-value in edgeEntry.
  25324.     Return false if there is no entry, true otherwise."
  25325.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveNextGlobalEdgeEntry'! !
  25326.  
  25327. !BalloonDebugEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/24/1998 21:00'!
  25328. primRenderImage: edge with: fill
  25329.     "Start/Proceed rendering the current scan line"
  25330.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveRenderImage'! !
  25331.  
  25332. !BalloonDebugEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/24/1998 21:00'!
  25333. primRenderScanline: edge with: fill
  25334.     "Start/Proceed rendering the current scan line"
  25335.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveRenderScanline'! !
  25336.  
  25337. !BalloonDebugEngine methodsFor: 'primitives-misc' stamp: 'ar 11/24/1998 20:59'!
  25338. primCopyBufferFrom: oldBuffer to: newBuffer
  25339.     "Copy the contents of oldBuffer into the (larger) newBuffer"
  25340.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveCopyBuffer'! !
  25341.  
  25342. !BalloonDebugEngine methodsFor: 'primitives-misc' stamp: 'ar 11/24/1998 20:59'!
  25343. primInitializeBuffer: buffer
  25344.     ^BalloonEnginePlugin doPrimitive: 'gePrimitiveInitializeBuffer'! !
  25345.  
  25346. BalloonEdgeData defines an entry in the internal edge table of the Balloon engine.
  25347.  
  25348. Instance Variables:
  25349.     index    <Integer>    The index into the external objects array of the associated graphics engine
  25350.     xValue    <Integer>    The computed x-value of the requested operation
  25351.     yValue    <Integer>    The y-value for the requested operation
  25352.     height    <Integer>    The (remaining) height of the edge
  25353.     source    <Object>        The object from the external objects array!
  25354. !BalloonEdgeData methodsFor: 'accessing' stamp: 'ar 10/27/1998 15:34'!
  25355. index
  25356.     ^index! !
  25357.  
  25358. !BalloonEdgeData methodsFor: 'accessing' stamp: 'ar 10/27/1998 15:35'!
  25359. index: anInteger
  25360.     index _ anInteger! !
  25361.  
  25362. !BalloonEdgeData methodsFor: 'accessing' stamp: 'ar 10/27/1998 20:13'!
  25363. lines
  25364.     ^lines! !
  25365.  
  25366. !BalloonEdgeData methodsFor: 'accessing' stamp: 'ar 10/27/1998 20:13'!
  25367. lines: anInteger
  25368.     ^lines _ anInteger! !
  25369.  
  25370. !BalloonEdgeData methodsFor: 'accessing' stamp: 'ar 10/27/1998 15:34'!
  25371. source
  25372.     ^source! !
  25373.  
  25374. !BalloonEdgeData methodsFor: 'accessing' stamp: 'ar 10/27/1998 21:39'!
  25375. source: anObject
  25376.     source _ anObject! !
  25377.  
  25378. !BalloonEdgeData methodsFor: 'accessing' stamp: 'ar 10/27/1998 15:34'!
  25379. xValue
  25380.     ^xValue! !
  25381.  
  25382. !BalloonEdgeData methodsFor: 'accessing' stamp: 'ar 10/27/1998 15:35'!
  25383. xValue: anInteger
  25384.     xValue _ anInteger! !
  25385.  
  25386. !BalloonEdgeData methodsFor: 'accessing' stamp: 'ar 10/27/1998 15:34'!
  25387. yValue
  25388.     ^yValue! !
  25389.  
  25390. !BalloonEdgeData methodsFor: 'accessing' stamp: 'ar 10/27/1998 15:35'!
  25391. yValue: anInteger
  25392.     yValue _ anInteger! !
  25393.  
  25394. !BalloonEdgeData methodsFor: 'accessing' stamp: 'ar 10/27/1998 19:56'!
  25395. zValue
  25396.     ^zValue! !
  25397.  
  25398. !BalloonEdgeData methodsFor: 'accessing' stamp: 'ar 10/27/1998 19:56'!
  25399. zValue: anInteger
  25400.     zValue _ anInteger! !
  25401.  
  25402. !BalloonEdgeData methodsFor: 'computing' stamp: 'ar 10/27/1998 15:53'!
  25403. stepToFirstScanLine
  25404.     source stepToFirstScanLineAt: yValue in: self! !
  25405.  
  25406. !BalloonEdgeData methodsFor: 'computing' stamp: 'ar 10/27/1998 15:53'!
  25407. stepToNextScanLine
  25408.     source stepToNextScanLineAt: yValue in: self! !
  25409.  
  25410. !BalloonEngine methodsFor: 'initialize' stamp: 'ar 11/25/1998 22:29'!
  25411. flush
  25412.     "Force all pending primitives onscreen"
  25413.     workBuffer ifNil:[^self].
  25414.     self copyBits.
  25415.     self release.! !
  25416.  
  25417. !BalloonEngine methodsFor: 'initialize' stamp: 'ar 12/30/1998 11:24'!
  25418. initialize
  25419.     externals _ OrderedCollection new: 100.
  25420.     span _ Bitmap new: 2048.
  25421.     bitBlt _ nil.
  25422.     self bitBlt: ((BitBlt toForm: Display) destRect: Display boundingBox; yourself).
  25423.     forms _ #().
  25424.     deferred _ false.! !
  25425.  
  25426. !BalloonEngine methodsFor: 'initialize' stamp: 'ar 11/25/1998 22:42'!
  25427. postFlushIfNeeded
  25428.     "Force all pending primitives onscreen"
  25429.     workBuffer ifNil:[^self].
  25430.     (deferred not or:[postFlushNeeded]) ifTrue:[
  25431.         self copyBits.
  25432.         self release].! !
  25433.  
  25434. !BalloonEngine methodsFor: 'initialize' stamp: 'ar 11/25/1998 22:43'!
  25435. preFlushIfNeeded
  25436.     "Force all pending primitives onscreen"
  25437.     workBuffer ifNil:[^self].
  25438.     self primFlushNeeded ifTrue:[
  25439.         self copyBits.
  25440.         self reset].! !
  25441.  
  25442. !BalloonEngine methodsFor: 'initialize' stamp: 'ar 11/11/1998 22:52'!
  25443. release
  25444.     self class recycleBuffer: workBuffer.
  25445.     workBuffer _ nil.! !
  25446.  
  25447. !BalloonEngine methodsFor: 'initialize' stamp: 'ar 11/25/1998 22:34'!
  25448. reset
  25449.     workBuffer ifNil:[workBuffer _ self class allocateOrRecycleBuffer: 10000].
  25450.     self primInitializeBuffer: workBuffer.
  25451.     self primSetAALevel: self aaLevel.
  25452.     self primSetOffset: destOffset.
  25453.     self primSetClipRect: clipRect.
  25454.     self primSetEdgeTransform: edgeTransform.
  25455.     self primSetColorTransform: colorTransform.
  25456.     forms _ #().! !
  25457.  
  25458. !BalloonEngine methodsFor: 'initialize' stamp: 'ar 11/25/1998 22:39'!
  25459. resetIfNeeded
  25460.     workBuffer ifNil:[self reset].
  25461.     self primSetEdgeTransform: edgeTransform.
  25462.     self primSetColorTransform: colorTransform.
  25463.     self primSetDepth: self primGetDepth + 1.
  25464.     postFlushNeeded _ false.! !
  25465.  
  25466. !BalloonEngine methodsFor: 'drawing' stamp: 'ar 10/11/1999 16:49'!
  25467. drawBezierShape: points fill: fillStyle borderWidth: borderWidth borderColor: borderFill transform: aTransform
  25468.     | fills |
  25469.     self edgeTransform: aTransform.
  25470.     self resetIfNeeded.
  25471.     fills _ self registerFill: fillStyle and: borderFill.
  25472.     self primAddBezierShape: points
  25473.         segments: (points size) // 3
  25474.         fill: (fills at: 1)
  25475.         lineWidth: borderWidth
  25476.         lineFill: (fills at: 2).
  25477.     self postFlushIfNeeded.! !
  25478.  
  25479. !BalloonEngine methodsFor: 'drawing' stamp: 'ar 11/26/1998 19:44'!
  25480. drawCompressedShape: shape transform: aTransform
  25481.     | fillIndexList |
  25482.     self edgeTransform: aTransform.
  25483.     self resetIfNeeded.
  25484.  
  25485.     fillIndexList _ self registerFills: shape fillStyles.
  25486.  
  25487.     self primAddCompressedShape: shape points
  25488.         segments: shape numSegments
  25489.         leftFills: shape leftFills
  25490.         rightFills: shape rightFills
  25491.         lineWidths: shape lineWidths
  25492.         lineFills: shape lineFills
  25493.         fillIndexList: fillIndexList.
  25494.     self postFlushIfNeeded.! !
  25495.  
  25496. !BalloonEngine methodsFor: 'drawing' stamp: 'ar 1/15/1999 03:02'!
  25497. drawGeneralBezierShape: contours fill: fillStyle borderWidth: borderWidth borderColor: borderFill transform: aTransform
  25498.  
  25499.     | fills |
  25500.     self edgeTransform: aTransform.
  25501.     self resetIfNeeded.
  25502.     fills _ self registerFill: fillStyle and: borderFill.
  25503.     contours do:[:points|
  25504.         self primAddBezierShape: points
  25505.             segments: (points size // 3)
  25506.             fill: (fills at: 1)
  25507.             lineWidth: borderWidth
  25508.             lineFill: (fills at: 2).
  25509.         "Note: To avoid premature flushing of the pipeline we need to
  25510.         reset the flush bit within the engine."
  25511.         self primFlushNeeded: false.
  25512.     ].
  25513.     "And set the flush bit afterwards"
  25514.     self primFlushNeeded: true.
  25515.     self postFlushIfNeeded.! !
  25516.  
  25517. !BalloonEngine methodsFor: 'drawing' stamp: 'ar 1/15/1999 03:02'!
  25518. drawGeneralPolygon: contours fill: fillStyle borderWidth: borderWidth borderColor: borderFill transform: aTransform
  25519.  
  25520.     | fills |
  25521.     self edgeTransform: aTransform.
  25522.     self resetIfNeeded.
  25523.     fills _ self registerFill: fillStyle and: borderFill.
  25524.     contours do:[:points|
  25525.         self primAddPolygon: points
  25526.             segments: points size
  25527.             fill: (fills at: 1)
  25528.             lineWidth: borderWidth
  25529.             lineFill: (fills at: 2).
  25530.         "Note: To avoid premature flushing of the pipeline we need to
  25531.         reset the flush bit within the engine."
  25532.         self primFlushNeeded: false.
  25533.     ].
  25534.     "And set the flush bit afterwards"
  25535.     self primFlushNeeded: true.
  25536.     self postFlushIfNeeded.! !
  25537.  
  25538. !BalloonEngine methodsFor: 'drawing' stamp: 'ar 11/26/1998 19:45'!
  25539. drawOval: rect fill: fillStyle borderWidth: borderWidth borderColor: borderColor transform: aMatrix
  25540.  
  25541.     | fills |
  25542.     self edgeTransform: aMatrix.
  25543.     self resetIfNeeded.
  25544.     fills _ self registerFill: fillStyle and: borderColor.
  25545.     self primAddOvalFrom: rect origin 
  25546.             to: rect corner
  25547.             fillIndex: (fills at: 1)
  25548.             borderWidth: borderWidth
  25549.             borderColor: (fills at: 2).
  25550.     self postFlushIfNeeded.! !
  25551.  
  25552. !BalloonEngine methodsFor: 'drawing' stamp: 'ar 11/26/1998 19:45'!
  25553. drawPolygon: points fill: fillStyle borderWidth: borderWidth borderColor: borderFill transform: aTransform
  25554.  
  25555.     | fills |
  25556.     self edgeTransform: aTransform.
  25557.     self resetIfNeeded.
  25558.     fills _ self registerFill: fillStyle and: borderFill.
  25559.     self primAddPolygon: points
  25560.         segments: points size
  25561.         fill: (fills at: 1)
  25562.         lineWidth: borderWidth
  25563.         lineFill: (fills at: 2).
  25564.     self postFlushIfNeeded.! !
  25565.  
  25566. !BalloonEngine methodsFor: 'drawing' stamp: 'ar 11/26/1998 19:45'!
  25567. drawRectangle: rect fill: fillStyle borderWidth: borderWidth borderColor: borderColor transform: aMatrix
  25568.  
  25569.     | fills |
  25570.     self edgeTransform: aMatrix.
  25571.     self resetIfNeeded.
  25572.     fills _ self registerFill: fillStyle and: borderColor.
  25573.     self primAddRectFrom: rect origin 
  25574.             to: rect corner
  25575.             fillIndex: (fills at: 1)
  25576.             borderWidth: borderWidth
  25577.             borderColor: (fills at: 2).
  25578.     self postFlushIfNeeded.! !
  25579.  
  25580. !BalloonEngine methodsFor: 'drawing' stamp: 'ar 1/14/1999 15:24'!
  25581. registerFill: aFillStyle
  25582.     "Register the given fill style."
  25583.     | theForm |
  25584.     aFillStyle ifNil:[^0].
  25585.     aFillStyle isSolidFill 
  25586.         ifTrue:[^aFillStyle scaledPixelValue32].
  25587.  
  25588.     aFillStyle isGradientFill ifTrue:[
  25589.         ^self primAddGradientFill: aFillStyle pixelRamp
  25590.             from: aFillStyle origin
  25591.             along: aFillStyle direction
  25592.             normal: aFillStyle normal
  25593.             radial: aFillStyle isRadialFill
  25594.         ].
  25595.     aFillStyle isBitmapFill ifTrue:[
  25596.         theForm _ aFillStyle form.
  25597.         theForm unhibernate.
  25598.         forms _ forms copyWith: theForm.
  25599.         ^self primAddBitmapFill: theForm
  25600.                 colormap: (theForm colormapIfNeededForDepth: 32)
  25601.                 tile: aFillStyle isTiled
  25602.                 from: aFillStyle origin
  25603.                 along: aFillStyle direction
  25604.                 normal: aFillStyle normal
  25605.                 xIndex: forms size].
  25606.     ^0! !
  25607.  
  25608. !BalloonEngine methodsFor: 'drawing' stamp: 'ar 11/26/1998 19:45'!
  25609. registerFill: fill1 and: fill2
  25610.     ^self registerFills: (Array with: fill1 with: fill2)! !
  25611.  
  25612. !BalloonEngine methodsFor: 'drawing' stamp: 'ar 1/14/1999 15:24'!
  25613. registerFill: aFillStyle transform: aTransform
  25614.  
  25615.     aFillStyle ifNil:[^0].
  25616.     aFillStyle isSolidFill 
  25617.         ifTrue:[^aFillStyle scaledPixelValue32].
  25618.  
  25619.     aFillStyle isGradientFill ifTrue:[
  25620.         ^self primAddGradientFill: aFillStyle pixelRamp
  25621.             from: aFillStyle origin
  25622.             along: aFillStyle direction
  25623.             normal: aFillStyle normal
  25624.             radial: aFillStyle isRadialFill
  25625.             matrix: aTransform.
  25626.         ].
  25627.     ^0! !
  25628.  
  25629. !BalloonEngine methodsFor: 'drawing' stamp: 'di 11/21/1999 20:15'!
  25630. registerFills: fills
  25631.  
  25632.     | fillIndexList index fillIndex |
  25633.     ((colorTransform notNil and:[colorTransform isAlphaTransform]) or:[
  25634.         fills anySatisfy: [:any| any notNil and:[any isTranslucent]]])
  25635.             ifTrue:[    self flush.
  25636.                     self reset.
  25637.                     postFlushNeeded _ true].
  25638.     fillIndexList _ WordArray new: fills size.
  25639.     index _ 1.
  25640.     [index <= fills size] whileTrue:[
  25641.         fillIndex _ self registerFill: (fills at: index).
  25642.         fillIndex == nil 
  25643.             ifTrue:[index _ 1] "Need to start over"
  25644.             ifFalse:[fillIndexList at: index put: fillIndex.
  25645.                     index _ index+1]
  25646.     ].
  25647.     ^fillIndexList! !
  25648.  
  25649. !BalloonEngine methodsFor: 'copying' stamp: 'ar 11/25/1998 00:45'!
  25650. canProceedAfter: failureReason
  25651.     "Check if we can proceed after the failureReason indicated."
  25652.     | newBuffer |
  25653.     failureReason = GErrorNeedFlush ifTrue:[
  25654.         "Need to flush engine before proceeding"
  25655.         self copyBits.
  25656.         self reset.
  25657.         ^true].
  25658.     failureReason = GErrorNoMoreSpace ifTrue:[
  25659.         "Work buffer is too small"
  25660.         newBuffer _ workBuffer species new: workBuffer size * 2.
  25661.         self primCopyBufferFrom: workBuffer to: newBuffer.
  25662.         workBuffer _ newBuffer.
  25663.         ^true].
  25664.     "Not handled"
  25665.     ^false! !
  25666.  
  25667. !BalloonEngine methodsFor: 'copying' stamp: 'ar 11/29/1998 18:22'!
  25668. copyBits
  25669.     self copyLoopFaster.! !
  25670.  
  25671. !BalloonEngine methodsFor: 'copying' stamp: 'ar 11/14/1998 19:32'!
  25672. copyLoop
  25673.     "This is the basic rendering loop using as little primitive support as possible."
  25674.     | finished edge fill |
  25675.     edge _ BalloonEdgeData new.
  25676.     fill _ BalloonFillData new.
  25677.     self primInitializeProcessing. "Initialize the GE for processing"
  25678.     [self primFinishedProcessing] whileFalse:[
  25679.         "Step 1: Process the edges in the global edge table that will be added in this step"
  25680.         [finished _ self primNextGlobalEdgeEntryInto: edge.
  25681.         finished] whileFalse:[
  25682.             edge source: (externals at: edge index).
  25683.             edge stepToFirstScanLine.
  25684.             self primAddActiveEdgeTableEntryFrom: edge].
  25685.  
  25686.         "Step 2: Scan the active edge table"
  25687.         [finished _ self primNextFillEntryInto: fill.
  25688.         finished] whileFalse:[
  25689.             fill source: (externals at: fill index).
  25690.             "Compute the new fill"
  25691.             fill computeFill.
  25692.             "And mix it in the out buffer"
  25693.             self primMergeFill: fill destForm bits from: fill].
  25694.  
  25695.         "Step 3: Display the current span buffer if necessary"
  25696.         self primDisplaySpanBuffer.
  25697.  
  25698.         "Step 4: Advance and resort the active edge table"
  25699.         [finished _ self primNextActiveEdgeEntryInto: edge.
  25700.         finished] whileFalse:[
  25701.             "If the index is zero then the edge has been handled by the GE"
  25702.             edge source: (externals at: edge index).
  25703.             edge stepToNextScanLine.
  25704.             self primChangeActiveEdgeTableEntryFrom: edge].
  25705.     ].
  25706.     self primGetTimes: Times.
  25707.     self primGetCounts: Counts.
  25708.     self primGetBezierStats: BezierStats.! !
  25709.  
  25710. !BalloonEngine methodsFor: 'copying' stamp: 'ar 11/14/1998 19:32'!
  25711. copyLoopFaster
  25712.     "This is a copy loop drawing one scan line at a time"
  25713.     | edge fill reason |
  25714.     edge _ BalloonEdgeData new.
  25715.     fill _ BalloonFillData new.
  25716.     [self primFinishedProcessing] whileFalse:[
  25717.         reason _ self primRenderScanline: edge with: fill.
  25718.         "reason ~= 0 means there has been a problem"
  25719.         reason = 0 ifFalse:[
  25720.             self processStopReason: reason edge: edge fill: fill.
  25721.         ].
  25722.     ].
  25723.     self primGetTimes: Times.
  25724.     self primGetCounts: Counts.
  25725.     self primGetBezierStats: BezierStats.! !
  25726.  
  25727. !BalloonEngine methodsFor: 'copying' stamp: 'ar 11/14/1998 19:33'!
  25728. copyLoopFastest
  25729.     "This is a copy loop drawing the entire image"
  25730.     | edge fill reason |
  25731.     edge _ BalloonEdgeData new.
  25732.     fill _ BalloonFillData new.
  25733.     [self primFinishedProcessing] whileFalse:[
  25734.         reason _ self primRenderImage: edge with: fill.
  25735.         "reason ~= 0 means there has been a problem"
  25736.         reason = 0 ifFalse:[
  25737.             self processStopReason: reason edge: edge fill: fill.
  25738.         ].
  25739.     ].
  25740.     self primGetTimes: Times.
  25741.     self primGetCounts: Counts.
  25742.     self primGetBezierStats: BezierStats.! !
  25743.  
  25744. !BalloonEngine methodsFor: 'copying' stamp: 'ar 11/11/1998 21:19'!
  25745. processStopReason: reason edge: edge fill: fill
  25746.     "The engine has stopped because of some reason.
  25747.     Try to figure out how to respond and do the necessary actions."
  25748.     "Note: The order of operations below can affect the speed"
  25749.  
  25750.     "Process unknown fills first"
  25751.     reason = GErrorFillEntry ifTrue:[
  25752.         fill source: (externals at: fill index).
  25753.         "Compute the new fill"
  25754.         fill computeFill.
  25755.         "And mix it in the out buffer"
  25756.         ^self primMergeFill: fill destForm bits from: fill].
  25757.  
  25758.     "Process unknown steppings in the AET second"
  25759.     reason = GErrorAETEntry ifTrue:[
  25760.         edge source: (externals at: edge index).
  25761.         edge stepToNextScanLine.
  25762.         ^self primChangeActiveEdgeTableEntryFrom: edge].
  25763.  
  25764.     "Process unknown entries in the GET third"
  25765.     reason = GErrorGETEntry ifTrue:[
  25766.         edge source: (externals at: edge index).
  25767.         edge stepToFirstScanLine.
  25768.         ^self primAddActiveEdgeTableEntryFrom: edge].
  25769.  
  25770.     "Process generic problems last"
  25771.     (self canProceedAfter: reason) ifTrue:[^self]. "Okay."
  25772.  
  25773.     ^self error:'Unkown stop reason in graphics engine'
  25774. ! !
  25775.  
  25776. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 11/11/1998 23:04'!
  25777. aaLevel
  25778.     ^aaLevel ifNil:[1]! !
  25779.  
  25780. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 11/11/1998 23:04'!
  25781. aaLevel: anInteger
  25782.     aaLevel _ (anInteger min: 4) max: 1.! !
  25783.  
  25784. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 10/29/1998 01:51'!
  25785. aaTransform
  25786.     "Return a transformation for the current anti-aliasing level"
  25787.     | matrix |
  25788.     matrix _ MatrixTransform2x3 withScale: (self aaLevel) asFloat asPoint.
  25789.     matrix offset: (self aaLevel // 2) asFloat asPoint.
  25790.     ^matrix composedWith:(MatrixTransform2x3 withOffset: destOffset asFloatPoint)! !
  25791.  
  25792. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 10/13/1998 03:04'!
  25793. bitBlt
  25794.     ^bitBlt! !
  25795.  
  25796. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 5/28/2000 15:02'!
  25797. bitBlt: aBitBlt
  25798.     bitBlt _ aBitBlt.
  25799.     bitBlt isNil ifTrue:[^self].
  25800.     self class primitiveSetBitBltPlugin: bitBlt getPluginName.
  25801.     self clipRect: bitBlt clipRect.
  25802.     bitBlt 
  25803.         sourceForm: (Form extent: span size @ 1 depth: 32 bits: span);
  25804.         sourceRect: (0@0 extent: 1@span size);
  25805.         colorMap: (Color colorMapIfNeededFrom: 32 to: bitBlt destForm depth);
  25806.         combinationRule: (bitBlt destForm depth >= 8 ifTrue:[34] ifFalse:[Form paint]).! !
  25807.  
  25808. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 11/1/1998 02:57'!
  25809. clipRect
  25810.     ^clipRect! !
  25811.  
  25812. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 10/13/1998 02:44'!
  25813. clipRect: aRect
  25814.     clipRect _ aRect truncated! !
  25815.  
  25816. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 11/24/1998 15:04'!
  25817. colorTransform
  25818.     ^colorTransform! !
  25819.  
  25820. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 11/24/1998 15:04'!
  25821. colorTransform: aColorTransform
  25822.     colorTransform _ aColorTransform! !
  25823.  
  25824. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 12/30/1998 11:24'!
  25825. deferred
  25826.     ^deferred! !
  25827.  
  25828. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 12/30/1998 11:24'!
  25829. deferred: aBoolean
  25830.     deferred _ aBoolean.! !
  25831.  
  25832. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 11/1/1998 02:56'!
  25833. destOffset
  25834.     ^destOffset! !
  25835.  
  25836. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 11/12/1998 00:22'!
  25837. destOffset: aPoint
  25838.     destOffset _ aPoint asIntegerPoint.
  25839.     bitBlt destX: aPoint x; destY: aPoint y.! !
  25840.  
  25841. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 11/25/1998 22:34'!
  25842. edgeTransform
  25843.     ^edgeTransform! !
  25844.  
  25845. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 11/25/1998 22:34'!
  25846. edgeTransform: aTransform
  25847.     edgeTransform _ aTransform.! !
  25848.  
  25849. !BalloonEngine methodsFor: 'accessing' stamp: 'ar 10/29/1998 01:51'!
  25850. fullTransformFrom: aMatrix
  25851.     | m |
  25852.     m _ self aaTransform composedWith: aMatrix.
  25853.     "m offset: m offset + destOffset."
  25854.     ^m! !
  25855.  
  25856. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/11/1998 21:55'!
  25857. primClipRectInto: rect
  25858.     <primitive: 'gePrimitiveGetClipRect'>
  25859.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive:'gePrimitiveGetClipRect'].
  25860.     ^self primitiveFailed! !
  25861.  
  25862. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/26/1998 19:46'!
  25863. primFlushNeeded
  25864.     <primitive:'gePrimitiveNeedsFlush'>
  25865.     ^self primitiveFailed! !
  25866.  
  25867. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 1/15/1999 03:03'!
  25868. primFlushNeeded: aBoolean
  25869.     <primitive:'gePrimitiveNeedsFlushPut'>
  25870.     ^self primitiveFailed! !
  25871.  
  25872. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/11/1998 21:55'!
  25873. primGetAALevel
  25874.     "Set the AA level"
  25875.     <primitive: 'gePrimitiveGetAALevel'>
  25876.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetAALevel'].
  25877.     ^self primitiveFailed! !
  25878.  
  25879. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/11/1998 21:55'!
  25880. primGetBezierStats: statsArray
  25881.     <primitive:'gePrimitiveGetBezierStats'>
  25882.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetBezierStats'].
  25883.     ^self primitiveFailed! !
  25884.  
  25885. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/11/1998 21:55'!
  25886. primGetClipRect: rect
  25887.     <primitive: 'gePrimitiveGetClipRect'>
  25888.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetClipRect'].
  25889.     ^self primitiveFailed! !
  25890.  
  25891. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/11/1998 21:55'!
  25892. primGetCounts: statsArray
  25893.     <primitive:'gePrimitiveGetCounts'>
  25894.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetCounts'].
  25895.     ^self primitiveFailed! !
  25896.  
  25897. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/26/1998 19:46'!
  25898. primGetDepth
  25899.     <primitive:'gePrimitiveGetDepth'>
  25900.     ^self primitiveFailed! !
  25901.  
  25902. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/11/1998 21:55'!
  25903. primGetFailureReason
  25904.     <primitive: 'gePrimitiveGetFailureReason'>
  25905.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetFailureReason'].
  25906.     ^0! !
  25907.  
  25908. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/11/1998 21:55'!
  25909. primGetOffset
  25910.     <primitive: 'gePrimitiveGetOffset'>
  25911.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetOffset'].
  25912.     ^self primitiveFailed! !
  25913.  
  25914. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/11/1998 21:55'!
  25915. primGetTimes: statsArray
  25916.     <primitive:'gePrimitiveGetTimes'>
  25917.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveGetTimes'].
  25918.     ^self primitiveFailed! !
  25919.  
  25920. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/11/1998 21:55'!
  25921. primSetAALevel: level
  25922.     "Set the AA level"
  25923.     <primitive: 'gePrimitiveSetAALevel'>
  25924.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveSetAALevel'].
  25925.     ^self primitiveFailed! !
  25926.  
  25927. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/11/1998 21:55'!
  25928. primSetClipRect: rect
  25929.     <primitive: 'gePrimitiveSetClipRect'>
  25930.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveSetClipRect'].
  25931.     ^self primitiveFailed! !
  25932.  
  25933. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/26/1998 19:47'!
  25934. primSetColorTransform: transform
  25935.     <primitive:'gePrimitiveSetColorTransform'>
  25936.     ^self primitiveFailed! !
  25937.  
  25938. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/26/1998 19:47'!
  25939. primSetDepth: depth
  25940.     <primitive:'gePrimitiveSetDepth'>
  25941.     ^self primitiveFailed! !
  25942.  
  25943. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/26/1998 19:47'!
  25944. primSetEdgeTransform: transform
  25945.     <primitive:'gePrimitiveSetEdgeTransform'>
  25946.     ^self primitiveFailed! !
  25947.  
  25948. !BalloonEngine methodsFor: 'primitives-access' stamp: 'ar 11/11/1998 21:55'!
  25949. primSetOffset: point
  25950.     <primitive: 'gePrimitiveSetOffset'>
  25951.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveSetOffset'].
  25952.     ^self primitiveFailed! !
  25953.  
  25954. !BalloonEngine methodsFor: 'primitives-adding' stamp: 'ar 11/26/1998 19:53'!
  25955. primAddBezierFrom: start to: end via: via leftFillIndex: leftFillIndex rightFillIndex: rightFillIndex
  25956.     <primitive: 'gePrimitiveAddBezier'>
  25957.     (self canProceedAfter: self primGetFailureReason) ifTrue:[
  25958.         ^self primAddBezierFrom: start to: end via: via leftFillIndex: leftFillIndex rightFillIndex: rightFillIndex
  25959.     ].
  25960.     ^self primitiveFailed! !
  25961.  
  25962. !BalloonEngine methodsFor: 'primitives-adding' stamp: 'ar 11/26/1998 19:53'!
  25963. primAddBezierShape: points segments: nSegments fill: fillStyle lineWidth: lineWidth lineFill: lineFill
  25964.     <primitive: 'gePrimitiveAddBezierShape'>
  25965.     (self canProceedAfter: self primGetFailureReason) ifTrue:[
  25966.         ^self primAddBezierShape: points segments: nSegments fill: fillStyle lineWidth: lineWidth lineFill: lineFill
  25967.     ].
  25968.     ^self primitiveFailed! !
  25969.  
  25970. !BalloonEngine methodsFor: 'primitives-adding' stamp: 'ar 11/27/1998 14:27'!
  25971. primAddBitmapFill: form colormap: cmap tile: tileFlag from: origin along: direction normal: normal xIndex: xIndex
  25972.     <primitive: 'gePrimitiveAddBitmapFill'>
  25973.     (self canProceedAfter: self primGetFailureReason) ifTrue:[
  25974.         ^self primAddBitmapFill: form colormap: cmap tile: tileFlag from: origin along: direction normal: normal xIndex: xIndex
  25975.     ].
  25976.     ^self primitiveFailed! !
  25977.  
  25978. !BalloonEngine methodsFor: 'primitives-adding' stamp: 'ar 11/26/1998 19:53'!
  25979. primAddCompressedShape: points segments: nSegments leftFills: leftFills rightFills: rightFills lineWidths: lineWidths lineFills: lineFills fillIndexList: fillIndexList
  25980.     <primitive: 'gePrimitiveAddCompressedShape'>
  25981.     (self canProceedAfter: self primGetFailureReason) ifTrue:[
  25982.         ^self primAddCompressedShape: points segments: nSegments leftFills: leftFills rightFills: rightFills lineWidths: lineWidths lineFills: lineFills fillIndexList: fillIndexList
  25983.     ].
  25984.     ^self primitiveFailed! !
  25985.  
  25986. !BalloonEngine methodsFor: 'primitives-adding' stamp: 'ar 11/26/1998 19:53'!
  25987. primAddExternalEdge: index initialX: initialX initialY: initialY initialZ: initialZ leftFillIndex: leftFillIndex rightFillIndex: rightFillIndex
  25988.     <primitive: 'gePrimitiveRegisterExternalEdge'>
  25989.     (self canProceedAfter: self primGetFailureReason) ifTrue:[
  25990.         ^self primAddExternalEdge: index initialX: initialX initialY: initialY initialZ: initialZ leftFillIndex: leftFillIndex rightFillIndex: rightFillIndex
  25991.     ].
  25992.     ^self primitiveFailed! !
  25993.  
  25994. !BalloonEngine methodsFor: 'primitives-adding' stamp: 'ar 11/26/1998 19:53'!
  25995. primAddExternalFill: index
  25996.     <primitive: 'gePrimitiveRegisterExternalFill'>
  25997.     (self canProceedAfter: self primGetFailureReason) ifTrue:[
  25998.         ^self primAddExternalFill: index
  25999.     ].
  26000.     ^self primitiveFailed! !
  26001.  
  26002. !BalloonEngine methodsFor: 'primitives-adding' stamp: 'ar 11/26/1998 19:53'!
  26003. primAddGradientFill: colorRamp from: origin along: direction normal: normal radial: isRadial
  26004.     <primitive: 'gePrimitiveAddGradientFill'>
  26005.     (self canProceedAfter: self primGetFailureReason) ifTrue:[
  26006.         ^self primAddGradientFill: colorRamp 
  26007.                 from: origin 
  26008.                 along: direction 
  26009.                 normal: normal 
  26010.                 radial: isRadial
  26011.     ].
  26012.     ^self primitiveFailed! !
  26013.  
  26014. !BalloonEngine methodsFor: 'primitives-adding' stamp: 'ar 11/26/1998 19:52'!
  26015. primAddLineFrom: start to: end leftFillIndex: leftFillIndex rightFillIndex: rightFillIndex
  26016.     <primitive: 'gePrimitiveAddLine'>
  26017.     (self canProceedAfter: self primGetFailureReason) ifTrue:[
  26018.         ^self primAddLineFrom: start to: end leftFillIndex: leftFillIndex rightFillIndex: rightFillIndex
  26019.     ].
  26020.     ^self primitiveFailed! !
  26021.  
  26022. !BalloonEngine methodsFor: 'primitives-adding' stamp: 'ar 11/26/1998 19:51'!
  26023. primAddOvalFrom: start to: end fillIndex: fillIndex borderWidth: width borderColor: pixelValue32
  26024.     <primitive: 'gePrimitiveAddOval'>
  26025.     (self canProceedAfter: self primGetFailureReason) ifTrue:[
  26026.         ^self primAddOvalFrom: start to: end fillIndex: fillIndex borderWidth: width borderColor: pixelValue32
  26027.     ].
  26028.     ^self primitiveFailed! !
  26029.  
  26030. !BalloonEngine methodsFor: 'primitives-adding' stamp: 'ar 11/26/1998 19:52'!
  26031. primAddPolygon: points segments: nSegments fill: fillStyle lineWidth: lineWidth lineFill: lineFill
  26032.     <primitive: 'gePrimitiveAddPolygon'>
  26033.     (self canProceedAfter: self primGetFailureReason) ifTrue:[
  26034.         ^self primAddPolygon: points segments: nSegments fill: fillStyle lineWidth: lineWidth lineFill: lineFill
  26035.     ].
  26036.     ^self primitiveFailed! !
  26037.  
  26038. !BalloonEngine methodsFor: 'primitives-adding' stamp: 'ar 1/14/1999 15:37'!
  26039. primAddRectFrom: start to: end fillIndex: fillIndex borderWidth: width borderColor: pixelValue32
  26040.     <primitive: 'gePrimitiveAddRect'>
  26041.     (self canProceedAfter: self primGetFailureReason) ifTrue:[
  26042.         ^self primAddRectFrom: start to: end fillIndex: fillIndex borderWidth: width borderColor: pixelValue32
  26043.     ].
  26044.     ^self primitiveFailed! !
  26045.  
  26046. !BalloonEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/14/1998 20:47'!
  26047. primAddActiveEdgeTableEntryFrom: edgeEntry
  26048.     "Add edge entry to the AET."
  26049.     <primitive: 'gePrimitiveAddActiveEdgeEntry'>
  26050.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveAddActiveEdgeEntry'].
  26051.     (self canProceedAfter: self primGetFailureReason) ifTrue:[
  26052.         ^self primAddActiveEdgeTableEntryFrom: edgeEntry
  26053.     ].
  26054.     ^self primitiveFailed! !
  26055.  
  26056. !BalloonEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/11/1998 21:56'!
  26057. primChangeActiveEdgeTableEntryFrom: edgeEntry
  26058.     "Change the entry in the active edge table from edgeEntry"
  26059.     <primitive: 'gePrimitiveChangedActiveEdgeEntry'>
  26060.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveChangedActiveEdgeEntry'].
  26061.     ^self primitiveFailed! !
  26062.  
  26063. !BalloonEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/11/1998 21:55'!
  26064. primDisplaySpanBuffer
  26065.     "Display the current scan line if necessary"
  26066.     <primitive: 'gePrimitiveDisplaySpanBuffer'>
  26067.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveDisplaySpanBuffer'].
  26068.     ^self primitiveFailed! !
  26069.  
  26070. !BalloonEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/11/1998 21:55'!
  26071. primFinishedProcessing
  26072.     "Return true if there are no more entries in AET and GET and the last scan line has been displayed"
  26073.     <primitive: 'gePrimitiveFinishedProcessing'>
  26074.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveFinishedProcessing'].
  26075.     ^self primitiveFailed! !
  26076.  
  26077. !BalloonEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/11/1998 21:55'!
  26078. primInitializeProcessing
  26079.     "Initialize processing in the GE.
  26080.     Create the active edge table and sort it."
  26081.     <primitive: 'gePrimitiveInitializeProcessing'>
  26082.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveInitializeProcessing'].
  26083.     ^self primitiveFailed! !
  26084.  
  26085. !BalloonEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/11/1998 21:55'!
  26086. primMergeFill: fillBitmap from: fill
  26087.     "Merge the filled bitmap into the current output buffer."
  26088.     <primitive: 'gePrimitiveMergeFillFrom'>
  26089.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveMergeFillFrom'].
  26090.     ^self primitiveFailed! !
  26091.  
  26092. !BalloonEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/11/1998 21:55'!
  26093. primNextActiveEdgeEntryInto: edgeEntry
  26094.     "Store the next entry of the AET at the current y-value in edgeEntry.
  26095.     Return false if there is no entry, true otherwise."
  26096.     <primitive: 'gePrimitiveNextActiveEdgeEntry'>
  26097.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveNextActiveEdgeEntry'].
  26098.     ^self primitiveFailed! !
  26099.  
  26100. !BalloonEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/11/1998 21:55'!
  26101. primNextFillEntryInto: fillEntry
  26102.     "Store the next fill entry of the active edge table in fillEntry.
  26103.     Return false if there is no such entry, true otherwise"
  26104.     <primitive: 'gePrimitiveNextFillEntry'>
  26105.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveNextFillEntry'].
  26106.     ^self primitiveFailed! !
  26107.  
  26108. !BalloonEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/11/1998 21:56'!
  26109. primNextGlobalEdgeEntryInto: edgeEntry
  26110.     "Store the next entry of the GET at the current y-value in edgeEntry.
  26111.     Return false if there is no entry, true otherwise."
  26112.     <primitive: 'gePrimitiveNextGlobalEdgeEntry'>
  26113.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveNextGlobalEdgeEntry'].
  26114.     ^self primitiveFailed! !
  26115.  
  26116. !BalloonEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/11/1998 21:55'!
  26117. primRenderImage: edge with: fill
  26118.     "Start/Proceed rendering the current scan line"
  26119.     <primitive: 'gePrimitiveRenderImage'>
  26120.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveRenderImage'].
  26121.     ^self primitiveFailed! !
  26122.  
  26123. !BalloonEngine methodsFor: 'primitives-incremental' stamp: 'ar 11/11/1998 21:55'!
  26124. primRenderScanline: edge with: fill
  26125.     "Start/Proceed rendering the current scan line"
  26126.     <primitive: 'gePrimitiveRenderScanline'>
  26127.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveRenderScanline'].
  26128.     ^self primitiveFailed! !
  26129.  
  26130. !BalloonEngine methodsFor: 'primitives-misc' stamp: 'ar 11/11/1998 21:55'!
  26131. primCopyBufferFrom: oldBuffer to: newBuffer
  26132.     "Copy the contents of oldBuffer into the (larger) newBuffer"
  26133.     <primitive: 'gePrimitiveCopyBuffer'>
  26134.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveCopyBuffer'].
  26135.     ^self primitiveFailed! !
  26136.  
  26137. !BalloonEngine methodsFor: 'primitives-misc' stamp: 'ar 11/11/1998 21:55'!
  26138. primInitializeBuffer: buffer
  26139.     <primitive: 'gePrimitiveInitializeBuffer'>
  26140.     Debug ifTrue:[^BalloonEnginePlugin doPrimitive: 'gePrimitiveInitializeBuffer'].
  26141.     ^self primitiveFailed! !
  26142.  
  26143. !BalloonEngine methodsFor: 'experimental' stamp: 'ar 11/12/1998 19:53'!
  26144. registerBezier: aCurve transformation: aMatrix
  26145.     self primAddBezierFrom: aCurve start
  26146.         to: aCurve end
  26147.         via: aCurve via
  26148.         leftFillIndex: (self registerFill: aCurve leftFill transform: aMatrix)
  26149.         rightFillIndex: (self registerFill: aCurve rightFill transform: aMatrix)
  26150.         matrix: aMatrix! !
  26151.  
  26152. !BalloonEngine methodsFor: 'experimental' stamp: 'ar 11/11/1998 21:15'!
  26153. registerBoundary: boundaryObject transformation: aMatrix
  26154.     | external |
  26155.     external _ boundaryObject asEdgeRepresentation: (self fullTransformFrom: aMatrix).
  26156.     self subdivideExternalEdge: external from: boundaryObject.
  26157. ! !
  26158.  
  26159. !BalloonEngine methodsFor: 'experimental' stamp: 'ar 11/12/1998 19:54'!
  26160. registerExternalEdge: externalEdge from: boundaryObject
  26161.     externals addLast: externalEdge.
  26162.     self primAddExternalEdge: externals size
  26163.         initialX: externalEdge initialX
  26164.         initialY: externalEdge initialY
  26165.         initialZ: externalEdge initialZ
  26166.         leftFillIndex: (self registerFill: boundaryObject leftFill transform: nil)
  26167.         rightFillIndex: (self registerFill: boundaryObject rightFill transform: nil)! !
  26168.  
  26169. !BalloonEngine methodsFor: 'experimental' stamp: 'ar 11/12/1998 19:54'!
  26170. registerLine: aLine transformation: aMatrix
  26171.     self primAddLineFrom: aLine start to: aLine end
  26172.         leftFillIndex: (self registerFill: aLine leftFill transform: aMatrix)
  26173.         rightFillIndex: (self registerFill: aLine rightFill transform: aMatrix)
  26174.         matrix: aMatrix! !
  26175.  
  26176. !BalloonEngine methodsFor: 'experimental' stamp: 'ar 11/11/1998 21:15'!
  26177. subdivideExternalEdge: external from: boundaryObject
  26178.     | external2 |
  26179.     external2 _ external subdivide.
  26180.     external2 notNil ifTrue:[
  26181.         self subdivideExternalEdge: external from: boundaryObject.
  26182.         self subdivideExternalEdge: external2 from: boundaryObject.
  26183.     ] ifFalse:[
  26184.         self registerExternalEdge: external from: boundaryObject.
  26185.     ].! !
  26186.  
  26187. !BalloonEngine methodsFor: 'profiling' stamp: 'ar 11/11/1998 21:16'!
  26188. doAddCompressedShape: points segments: nSegments leftFills: leftFills rightFills: rightFills lineWidths: lineWidths lineFills: lineFills fillIndexList: fillIndexList matrix: aMatrix
  26189.     "Note: This method is for profiling the overhead of loading a compressed shape into the engine."
  26190.     ^self primAddCompressedShape: points segments: nSegments leftFills: leftFills rightFills: rightFills lineWidths: lineWidths lineFills: lineFills fillIndexList: fillIndexList matrix: aMatrix! !
  26191.  
  26192. !BalloonEngine class methodsFor: 'instance creation' stamp: 'ar 10/9/1998 21:44'!
  26193. new
  26194.     ^super new initialize! !
  26195.  
  26196. !BalloonEngine class methodsFor: 'class initialization' stamp: 'ar 11/11/1998 22:49'!
  26197. initialize
  26198.     "BalloonEngine initialize"
  26199.     BufferCache _ WeakArray new: 1.
  26200.     Smalltalk garbageCollect. "Make the cache old"
  26201.     CacheProtect _ Semaphore forMutualExclusion.
  26202.     Times _ WordArray new: 10.
  26203.     Counts _ WordArray new: 10.
  26204.     BezierStats _ WordArray new: 4.
  26205.     Debug ifNil:[Debug _ false].! !
  26206.  
  26207. !BalloonEngine class methodsFor: 'accessing' stamp: 'ar 10/25/1998 17:37'!
  26208. debug: aBoolean
  26209.     "BalloonEngine debug: true"
  26210.     "BalloonEngine debug: false"
  26211.     Debug _ aBoolean! !
  26212.  
  26213. !BalloonEngine class methodsFor: 'accessing' stamp: 'ar 1/12/1999 11:17'!
  26214. doProfileStats: aBool
  26215.     "Note: On Macintosh systems turning on profiling can significantly
  26216.     degrade the performance of Balloon since we're using the high
  26217.     accuracy timer for measuring."
  26218.     "BalloonEngine doProfileStats: true"
  26219.     "BalloonEngine doProfileStats: false"
  26220.     <primitive: 'gePrimitiveDoProfileStats'>
  26221.     ^false! !
  26222.  
  26223. !BalloonEngine class methodsFor: 'accessing' stamp: 'ar 10/30/1998 23:57'!
  26224. printBezierStats
  26225.     "BalloonEngine printBezierStats"
  26226.     "BalloonEngine resetBezierStats"
  26227.     Transcript 
  26228.         cr; nextPutAll:'Bezier statistics:';
  26229.         crtab; print: (BezierStats at: 1); tab; nextPutAll:' non-monoton curves splitted';
  26230.         crtab; print: (BezierStats at: 2); tab; nextPutAll:' curves splitted for numerical accuracy';
  26231.         crtab; print: (BezierStats at: 3); tab; nextPutAll:' curves splitted to avoid integer overflow';
  26232.         crtab; print: (BezierStats at: 4); tab; nextPutAll:' curves internally converted to lines';
  26233.     endEntry.! !
  26234.  
  26235. !BalloonEngine class methodsFor: 'accessing' stamp: 'ar 10/28/1998 23:59'!
  26236. printStat: time count: n string: aString
  26237.     Transcript
  26238.         cr;
  26239.         print: time; tab;
  26240.         nextPutAll:' mSecs -- ';
  26241.         print: n; tab;
  26242.         nextPutAll:' ops -- ';
  26243.         print: ((time asFloat / (n max: 1) asFloat) roundTo: 0.01); tab;
  26244.         nextPutAll: ' avg. mSecs/op -- ';
  26245.         nextPutAll: aString.! !
  26246.  
  26247. !BalloonEngine class methodsFor: 'accessing' stamp: 'ar 1/12/1999 10:52'!
  26248. printStats
  26249.     "BalloonEngine doProfileStats: true"
  26250.     "BalloonEngine printStats"
  26251.     "BalloonEngine resetStats"
  26252.     Transcript cr; nextPutAll:'/************** BalloonEngine statistics ****************/'.
  26253.     self printStat: (Times at: 1) count: (Counts at: 1) string: 'Initialization'.
  26254.     self printStat: (Times at: 2) count: (Counts at: 2) string: 'Finish test'.
  26255.     self printStat: (Times at: 3) count: (Counts at: 3) string: 'Fetching/Adding GET entries'.
  26256.     self printStat: (Times at: 4) count: (Counts at: 4) string: 'Adding AET entries'.
  26257.     self printStat: (Times at: 5) count: (Counts at: 5) string: 'Fetching/Computing fills'.
  26258.     self printStat: (Times at: 6) count: (Counts at: 6) string: 'Merging fills'.
  26259.     self printStat: (Times at: 7) count: (Counts at: 7) string: 'Displaying span buffer'.
  26260.     self printStat: (Times at: 8) count: (Counts at: 8) string: 'Fetching/Updating AET entries'.
  26261.     self printStat: (Times at: 9) count: (Counts at: 9) string: 'Changing AET entries'.
  26262.     Transcript cr; print: Times sum; nextPutAll:' mSecs for all operations'.
  26263.     Transcript cr; print: Counts sum; nextPutAll: ' overall operations'.
  26264.     Transcript endEntry.! !
  26265.  
  26266. !BalloonEngine class methodsFor: 'accessing' stamp: 'ar 10/30/1998 23:57'!
  26267. resetBezierStats
  26268.     BezierStats _ WordArray new: 4.! !
  26269.  
  26270. !BalloonEngine class methodsFor: 'accessing' stamp: 'ar 10/28/1998 23:38'!
  26271. resetStats
  26272.     Times _ WordArray new: 10.
  26273.     Counts _ WordArray new: 10.! !
  26274.  
  26275. !BalloonEngine class methodsFor: 'private' stamp: 'ar 11/11/1998 22:50'!
  26276. allocateOrRecycleBuffer: initialSize
  26277.     "Try to recycly a buffer. If this is not possibly, create a new one."
  26278.     | buffer |
  26279.     CacheProtect critical:[
  26280.         buffer _ BufferCache at: 1.
  26281.         BufferCache at: 1 put: nil.
  26282.     ].
  26283.     ^buffer ifNil:[BalloonBuffer new: initialSize]! !
  26284.  
  26285. !BalloonEngine class methodsFor: 'private' stamp: 'ar 5/28/2000 22:17'!
  26286. primitiveSetBitBltPlugin: pluginName
  26287.     <primitive: 'primitiveSetBitBltPlugin' module: 'B2DPlugin'>
  26288.     ^nil! !
  26289.  
  26290. !BalloonEngine class methodsFor: 'private' stamp: 'ar 11/11/1998 22:51'!
  26291. recycleBuffer: balloonBuffer
  26292.     "Try to keep the buffer for later drawing operations."
  26293.     | buffer |
  26294.     CacheProtect critical:[
  26295.         buffer _ BufferCache at: 1.
  26296.         (buffer isNil or:[buffer size < balloonBuffer size] )
  26297.             ifTrue:[BufferCache at: 1 put: balloonBuffer].
  26298.     ].! !
  26299.  
  26300. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 00:34'!
  26301. aaColorMaskGet
  26302.     ^workBuffer at: GWAAColorMask! !
  26303.  
  26304. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 00:34'!
  26305. aaColorMaskPut: value
  26306.     ^workBuffer at: GWAAColorMask put: value! !
  26307.  
  26308. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 00:34'!
  26309. aaColorShiftGet
  26310.     ^workBuffer at: GWAAColorShift! !
  26311.  
  26312. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 00:34'!
  26313. aaColorShiftPut: value
  26314.     ^workBuffer at: GWAAColorShift put: value! !
  26315.  
  26316. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 00:34'!
  26317. aaHalfPixelGet
  26318.     ^workBuffer at: GWAAHalfPixel! !
  26319.  
  26320. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 00:35'!
  26321. aaHalfPixelPut: value
  26322.     ^workBuffer at: GWAAHalfPixel put: value! !
  26323.  
  26324. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 00:35'!
  26325. aaLevelGet
  26326.     ^workBuffer at: GWAALevel! !
  26327.  
  26328. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 00:35'!
  26329. aaLevelPut: value
  26330.     ^workBuffer at: GWAALevel put: value! !
  26331.  
  26332. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 00:35'!
  26333. aaScanMaskGet
  26334.     ^workBuffer at: GWAAScanMask! !
  26335.  
  26336. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 00:35'!
  26337. aaScanMaskPut: value
  26338.     ^workBuffer at: GWAAScanMask put: value! !
  26339.  
  26340. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 00:35'!
  26341. aaShiftGet
  26342.     ^workBuffer at: GWAAShift! !
  26343.  
  26344. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 00:36'!
  26345. aaShiftPut: value
  26346.     ^workBuffer at: GWAAShift put: value! !
  26347.  
  26348. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:27'!
  26349. aetStartGet
  26350.     ^workBuffer at: GWAETStart! !
  26351.  
  26352. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:29'!
  26353. aetStartPut: value
  26354.     ^workBuffer at: GWAETStart put: value! !
  26355.  
  26356. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:27'!
  26357. aetUsedGet
  26358.     ^workBuffer at: GWAETUsed! !
  26359.  
  26360. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:29'!
  26361. aetUsedPut: value
  26362.     ^workBuffer at: GWAETUsed put: value! !
  26363.  
  26364. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/29/1998 00:43'!
  26365. clearSpanBufferGet
  26366.     ^workBuffer at: GWClearSpanBuffer! !
  26367.  
  26368. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/29/1998 00:44'!
  26369. clearSpanBufferPut: value
  26370.     ^workBuffer at: GWClearSpanBuffer put: value! !
  26371.  
  26372. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 18:46'!
  26373. clipMaxXGet
  26374.     ^workBuffer at: GWClipMaxX! !
  26375.  
  26376. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 18:46'!
  26377. clipMaxXPut: value
  26378.     ^workBuffer at: GWClipMaxX put: value! !
  26379.  
  26380. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 18:46'!
  26381. clipMaxYGet
  26382.     ^workBuffer at: GWClipMaxY! !
  26383.  
  26384. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 18:46'!
  26385. clipMaxYPut: value
  26386.     ^workBuffer at: GWClipMaxY put: value! !
  26387.  
  26388. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 18:46'!
  26389. clipMinXGet
  26390.     ^workBuffer at: GWClipMinX! !
  26391.  
  26392. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 18:47'!
  26393. clipMinXPut: value
  26394.     ^workBuffer at: GWClipMinX put: value! !
  26395.  
  26396. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 18:47'!
  26397. clipMinYGet
  26398.     ^workBuffer at: GWClipMinY! !
  26399.  
  26400. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 18:47'!
  26401. clipMinYPut: value
  26402.     ^workBuffer at: GWClipMinY put: value! !
  26403.  
  26404. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 11/24/1998 21:36'!
  26405. colorTransform
  26406.     self returnTypeC:'float *'.
  26407.     ^self cCoerce: workBuffer + GWColorTransform to:'float *'! !
  26408.  
  26409. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:27'!
  26410. currentYGet
  26411.     ^workBuffer at: GWCurrentY! !
  26412.  
  26413. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 21:27'!
  26414. currentYPut: value
  26415.     ^workBuffer at: GWCurrentY put: value! !
  26416.  
  26417. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 11/24/1998 20:28'!
  26418. currentZGet
  26419.     ^workBuffer at: GWCurrentZ! !
  26420.  
  26421. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 11/24/1998 20:29'!
  26422. currentZPut: value
  26423.     ^workBuffer at: GWCurrentZ put: value! !
  26424.  
  26425. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/29/1998 16:23'!
  26426. destOffsetXGet
  26427.     ^workBuffer at: GWDestOffsetX! !
  26428.  
  26429. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/29/1998 16:24'!
  26430. destOffsetXPut: value
  26431.     ^workBuffer at: GWDestOffsetX put: value! !
  26432.  
  26433. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/29/1998 16:23'!
  26434. destOffsetYGet
  26435.     ^workBuffer at: GWDestOffsetY! !
  26436.  
  26437. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/29/1998 16:24'!
  26438. destOffsetYPut: value
  26439.     ^workBuffer at: GWDestOffsetY put: value! !
  26440.  
  26441. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 11/24/1998 21:36'!
  26442. edgeTransform
  26443.     self returnTypeC:'float *'.
  26444.     ^self cCoerce: workBuffer + GWEdgeTransform to:'float *'! !
  26445.  
  26446. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:27'!
  26447. fillMaxXGet
  26448.     ^workBuffer at: GWFillMaxX! !
  26449.  
  26450. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:29'!
  26451. fillMaxXPut: value
  26452.     ^workBuffer at: GWFillMaxX put: value! !
  26453.  
  26454. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:27'!
  26455. fillMaxYGet
  26456.     ^workBuffer at: GWFillMaxY! !
  26457.  
  26458. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:30'!
  26459. fillMaxYPut: value
  26460.     ^workBuffer at: GWFillMaxY put: value! !
  26461.  
  26462. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:27'!
  26463. fillMinXGet
  26464.     ^workBuffer at: GWFillMinX! !
  26465.  
  26466. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:30'!
  26467. fillMinXPut: value
  26468.     ^workBuffer at: GWFillMinX put: value! !
  26469.  
  26470. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:27'!
  26471. fillMinYGet
  26472.     ^workBuffer at: GWFillMinY! !
  26473.  
  26474. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:30'!
  26475. fillMinYPut: value
  26476.     ^workBuffer at: GWFillMinY put: value! !
  26477.  
  26478. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:27'!
  26479. fillOffsetXGet
  26480.     ^workBuffer at: GWFillOffsetX! !
  26481.  
  26482. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:30'!
  26483. fillOffsetXPut: value
  26484.     ^workBuffer at: GWFillOffsetX put: value! !
  26485.  
  26486. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:27'!
  26487. fillOffsetYGet
  26488.     ^workBuffer at: GWFillOffsetY! !
  26489.  
  26490. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:30'!
  26491. fillOffsetYPut: value
  26492.     ^workBuffer at: GWFillOffsetY put: value! !
  26493.  
  26494. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/29/1998 17:08'!
  26495. firstPointListGet
  26496.     ^workBuffer at: GWPointListFirst! !
  26497.  
  26498. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/29/1998 17:08'!
  26499. firstPointListPut: value
  26500.     ^workBuffer at: GWPointListFirst put: value! !
  26501.  
  26502. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:27'!
  26503. getStartGet
  26504.     ^workBuffer at: GWGETStart! !
  26505.  
  26506. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:30'!
  26507. getStartPut: value
  26508.     ^workBuffer at: GWGETStart put: value! !
  26509.  
  26510. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:27'!
  26511. getUsedGet
  26512.     ^workBuffer at: GWGETUsed! !
  26513.  
  26514. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:31'!
  26515. getUsedPut: value
  26516.     ^workBuffer at: GWGETUsed put: value! !
  26517.  
  26518. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 11/24/1998 21:36'!
  26519. hasColorTransformGet
  26520.     ^workBuffer at: GWHasColorTransform! !
  26521.  
  26522. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 11/24/1998 21:36'!
  26523. hasColorTransformPut: value
  26524.     ^workBuffer at: GWHasColorTransform put: value! !
  26525.  
  26526. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 11/24/1998 21:36'!
  26527. hasEdgeTransformGet
  26528.     ^workBuffer at: GWHasEdgeTransform! !
  26529.  
  26530. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 11/24/1998 21:35'!
  26531. hasEdgeTransformPut: value
  26532.     ^workBuffer at: GWHasEdgeTransform put: value! !
  26533.  
  26534. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 11/9/1998 15:36'!
  26535. incrementStat: statIndex by: value
  26536.  
  26537.     ^workBuffer at: statIndex put: (workBuffer at: statIndex) + value! !
  26538.  
  26539. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:28'!
  26540. lastExportedEdgeGet
  26541.     ^workBuffer at: GWLastExportedEdge! !
  26542.  
  26543. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 20:11'!
  26544. lastExportedEdgePut: value
  26545.     ^workBuffer at: GWLastExportedEdge put: value! !
  26546.  
  26547. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 14:24'!
  26548. lastExportedFillGet
  26549.     ^workBuffer at: GWLastExportedFill! !
  26550.  
  26551. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 14:24'!
  26552. lastExportedFillPut: value
  26553.     ^workBuffer at: GWLastExportedFill put: value! !
  26554.  
  26555. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 16:51'!
  26556. lastExportedLeftXGet
  26557.     ^workBuffer at: GWLastExportedLeftX! !
  26558.  
  26559. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 16:51'!
  26560. lastExportedLeftXPut: value
  26561.     ^workBuffer at: GWLastExportedLeftX put: value! !
  26562.  
  26563. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 16:51'!
  26564. lastExportedRightXGet
  26565.     ^workBuffer at: GWLastExportedRightX! !
  26566.  
  26567. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 16:51'!
  26568. lastExportedRightXPut: value
  26569.     ^workBuffer at: GWLastExportedRightX put: value! !
  26570.  
  26571. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:28'!
  26572. magicNumberGet
  26573.     ^workBuffer at: GWMagicIndex! !
  26574.  
  26575. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:39'!
  26576. magicNumberPut: value
  26577.     ^workBuffer at: GWMagicIndex put: value! !
  26578.  
  26579. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 11/25/1998 00:20'!
  26580. needsFlushGet
  26581.     ^workBuffer at: GWNeedsFlush! !
  26582.  
  26583. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 11/25/1998 00:20'!
  26584. needsFlushPut: value
  26585.     ^workBuffer at: GWNeedsFlush put: value! !
  26586.  
  26587. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:28'!
  26588. objStartGet
  26589.     ^workBuffer at: GWObjStart! !
  26590.  
  26591. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:32'!
  26592. objStartPut: value
  26593.     ^workBuffer at: GWObjStart put: value! !
  26594.  
  26595. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:28'!
  26596. objUsedGet
  26597.     ^workBuffer at: GWObjUsed! !
  26598.  
  26599. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:32'!
  26600. objUsedPut: value
  26601.     ^workBuffer at: GWObjUsed put: value! !
  26602.  
  26603. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 16:33'!
  26604. point1Get
  26605.     self returnTypeC:'int *'.
  26606.     ^self cCoerce: workBuffer + GWPoint1 to:'int *'! !
  26607.  
  26608. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 16:34'!
  26609. point2Get
  26610.     self returnTypeC:'int *'.
  26611.     ^self cCoerce: workBuffer + GWPoint2 to:'int *'! !
  26612.  
  26613. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/28/1998 16:34'!
  26614. point3Get
  26615.     self returnTypeC:'int *'.
  26616.     ^self cCoerce: workBuffer + GWPoint3 to:'int *'! !
  26617.  
  26618. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 11/1/1998 03:13'!
  26619. point4Get
  26620.     self returnTypeC:'int *'.
  26621.     ^self cCoerce: workBuffer + GWPoint4 to:'int *'! !
  26622.  
  26623. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:28'!
  26624. spanEndAAGet
  26625.     ^workBuffer at: GWSpanEndAA! !
  26626.  
  26627. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:31'!
  26628. spanEndAAPut: value
  26629.     ^workBuffer at: GWSpanEndAA put: value! !
  26630.  
  26631. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:28'!
  26632. spanEndGet
  26633.     ^workBuffer at: GWSpanEnd! !
  26634.  
  26635. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:31'!
  26636. spanEndPut: value
  26637.     ^workBuffer at: GWSpanEnd put: value! !
  26638.  
  26639. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:28'!
  26640. spanSizeGet
  26641.     ^workBuffer at: GWSpanSize! !
  26642.  
  26643. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:31'!
  26644. spanSizePut: value
  26645.     ^workBuffer at: GWSpanSize put: value! !
  26646.  
  26647. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:28'!
  26648. spanStartGet
  26649.     ^workBuffer at: GWSpanStart! !
  26650.  
  26651. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:31'!
  26652. spanStartPut: value
  26653.     ^workBuffer at: GWSpanStart put: value! !
  26654.  
  26655. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:28'!
  26656. stateGet
  26657.     ^workBuffer at: GWState! !
  26658.  
  26659. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:31'!
  26660. statePut: value
  26661.     ^workBuffer at: GWState put: value! !
  26662.  
  26663. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:28'!
  26664. stopReasonGet
  26665.     ^workBuffer at: GWStopReason! !
  26666.  
  26667. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:31'!
  26668. stopReasonPut: value
  26669.     ^workBuffer at: GWStopReason put: value! !
  26670.  
  26671. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:28'!
  26672. wbSizeGet
  26673.     ^workBuffer at: GWSize! !
  26674.  
  26675. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:37'!
  26676. wbSizePut: value
  26677.     ^workBuffer at: GWSize put: value! !
  26678.  
  26679. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 23:29'!
  26680. wbTopGet
  26681.     ^workBuffer at: GWBufferTop! !
  26682.  
  26683. !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 10/27/1998 18:32'!
  26684. wbTopPut: value
  26685.     ^workBuffer at: GWBufferTop put: value! !
  26686.  
  26687. !BalloonEngineBase methodsFor: 'accessing objects' stamp: 'ar 11/24/1998 22:22'!
  26688. obj: object at: index
  26689.     ^objBuffer at: object + index! !
  26690.  
  26691. !BalloonEngineBase methodsFor: 'accessing objects' stamp: 'ar 11/24/1998 22:22'!
  26692. obj: object at: index put: value
  26693.     ^objBuffer at: object + index put: value! !
  26694.  
  26695. !BalloonEngineBase methodsFor: 'accessing objects' stamp: 'ar 11/24/1998 22:02'!
  26696. objectHeaderOf: obj
  26697.  
  26698.     ^self makeUnsignedFrom:(self obj: obj at: GEObjectType)! !
  26699.  
  26700. !BalloonEngineBase methodsFor: 'accessing objects' stamp: 'ar 11/24/1998 22:03'!
  26701. objectIndexOf: obj
  26702.  
  26703.     ^self obj: obj at: GEObjectIndex! !
  26704.  
  26705. !BalloonEngineBase methodsFor: 'accessing objects' stamp: 'ar 11/24/1998 22:03'!
  26706. objectIndexOf: obj put: value
  26707.  
  26708.     ^self obj: obj at: GEObjectIndex put: value! !
  26709.  
  26710. !BalloonEngineBase methodsFor: 'accessing objects' stamp: 'ar 11/24/1998 22:03'!
  26711. objectLengthOf: obj
  26712.  
  26713.     ^self obj: obj at: GEObjectLength! !
  26714.  
  26715. !BalloonEngineBase methodsFor: 'accessing objects' stamp: 'ar 11/24/1998 22:03'!
  26716. objectLengthOf: obj put: value
  26717.  
  26718.     ^self obj: obj at: GEObjectLength put: value! !
  26719.  
  26720. !BalloonEngineBase methodsFor: 'accessing objects' stamp: 'ar 11/24/1998 22:03'!
  26721. objectTypeOf: obj
  26722.  
  26723.     ^(self makeUnsignedFrom:(self obj: obj at: GEObjectType)) bitAnd: GEPrimitiveTypeMask! !
  26724.  
  26725. !BalloonEngineBase methodsFor: 'accessing objects' stamp: 'ar 11/24/1998 22:03'!
  26726. objectTypeOf: obj put: value
  26727.  
  26728.     ^self obj: obj at: GEObjectType put: value! !
  26729.  
  26730. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/9/1998 15:35'!
  26731. edgeFillsInvalidate: edge
  26732.  
  26733.     ^self objectTypeOf: edge put: 
  26734.         ((self objectTypeOf: edge) bitOr: GEEdgeFillsInvalid)! !
  26735.  
  26736. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/9/1998 15:35'!
  26737. edgeFillsValidate: edge
  26738.  
  26739.     ^self objectTypeOf: edge put: 
  26740.         ((self objectTypeOf: edge) bitAnd: GEEdgeFillsInvalid bitInvert32)! !
  26741.  
  26742. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/24/1998 22:04'!
  26743. edgeLeftFillOf: edge
  26744.  
  26745.     ^self obj: edge at: GEFillIndexLeft! !
  26746.  
  26747. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/24/1998 22:04'!
  26748. edgeLeftFillOf: edge put: value
  26749.  
  26750.     ^self obj: edge at: GEFillIndexLeft put: value! !
  26751.  
  26752. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/24/1998 22:04'!
  26753. edgeNumLinesOf: edge
  26754.  
  26755.     ^self obj: edge at: GENumLines! !
  26756.  
  26757. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/24/1998 22:04'!
  26758. edgeNumLinesOf: edge put: value
  26759.  
  26760.     ^self obj: edge at: GENumLines put: value! !
  26761.  
  26762. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/24/1998 22:05'!
  26763. edgeRightFillOf: edge
  26764.  
  26765.     ^self obj: edge at: GEFillIndexRight! !
  26766.  
  26767. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/24/1998 22:05'!
  26768. edgeRightFillOf: edge put: value
  26769.  
  26770.     ^self obj: edge at: GEFillIndexRight put: value! !
  26771.  
  26772. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/9/1998 15:35'!
  26773. edgeTypeOf: edge
  26774.     "Return the edge type (e.g., witout the wide edge flag)"
  26775.  
  26776.     ^(self objectTypeOf: edge) >> 1! !
  26777.  
  26778. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/24/1998 22:05'!
  26779. edgeXValueOf: edge
  26780.  
  26781.     ^self obj: edge at: GEXValue! !
  26782.  
  26783. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/24/1998 22:05'!
  26784. edgeXValueOf: edge put: value
  26785.  
  26786.     ^self obj: edge at: GEXValue put: value! !
  26787.  
  26788. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/24/1998 22:05'!
  26789. edgeYValueOf: edge
  26790.  
  26791.     ^self obj: edge at: GEYValue! !
  26792.  
  26793. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/24/1998 22:06'!
  26794. edgeYValueOf: edge put: value
  26795.  
  26796.     ^self obj: edge at: GEYValue put: value! !
  26797.  
  26798. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/24/1998 22:06'!
  26799. edgeZValueOf: edge
  26800.  
  26801.     ^self obj: edge at: GEZValue! !
  26802.  
  26803. !BalloonEngineBase methodsFor: 'accessing edges' stamp: 'ar 11/24/1998 22:06'!
  26804. edgeZValueOf: edge put: value
  26805.  
  26806.     ^self obj: edge at: GEZValue put: value! !
  26807.  
  26808. !BalloonEngineBase methodsFor: 'accessing stack' stamp: 'ar 10/31/1998 00:43'!
  26809. wbStackClear
  26810.     self wbTopPut: self wbSizeGet.! !
  26811.  
  26812. !BalloonEngineBase methodsFor: 'accessing stack' stamp: 'ar 11/9/1998 15:34'!
  26813. wbStackPop: nItems
  26814.  
  26815.     self wbTopPut: self wbTopGet + nItems.! !
  26816.  
  26817. !BalloonEngineBase methodsFor: 'accessing stack' stamp: 'ar 10/30/1998 17:16'!
  26818. wbStackPush: nItems
  26819.     (self allocateStackEntry: nItems) ifFalse:[^false].
  26820.     self wbTopPut: self wbTopGet - nItems.
  26821.     ^true! !
  26822.  
  26823. !BalloonEngineBase methodsFor: 'accessing stack' stamp: 'ar 10/30/1998 17:17'!
  26824. wbStackSize
  26825.     ^self wbSizeGet - self wbTopGet! !
  26826.  
  26827. !BalloonEngineBase methodsFor: 'accessing stack' stamp: 'ar 11/9/1998 15:34'!
  26828. wbStackValue: index
  26829.  
  26830.     ^workBuffer at: self wbTopGet + index! !
  26831.  
  26832. !BalloonEngineBase methodsFor: 'accessing stack' stamp: 'ar 11/9/1998 15:34'!
  26833. wbStackValue: index put: value
  26834.  
  26835.     ^workBuffer at: self wbTopGet + index put: value! !
  26836.  
  26837. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 11/7/1998 22:25'!
  26838. fillTypeOf: fill
  26839.     ^((self objectTypeOf: fill) bitAnd: GEPrimitiveFillMask) >> 8! !
  26840.  
  26841. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 10/30/1998 19:08'!
  26842. stackFillDepth: index
  26843.     ^self wbStackValue: index+1! !
  26844.  
  26845. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 10/30/1998 19:08'!
  26846. stackFillDepth: index put: value
  26847.     ^self wbStackValue: index+1 put: value! !
  26848.  
  26849. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 11/25/1998 14:31'!
  26850. stackFillEntryLength
  26851.     ^3! !
  26852.  
  26853. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 11/25/1998 14:35'!
  26854. stackFillRightX: index
  26855.     ^self wbStackValue: index+2! !
  26856.  
  26857. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 11/25/1998 14:35'!
  26858. stackFillRightX: index put: value
  26859.     ^self wbStackValue: index+2 put: value! !
  26860.  
  26861. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 10/30/1998 19:10'!
  26862. stackFillSize
  26863.     ^self wbStackSize! !
  26864.  
  26865. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 10/30/1998 19:09'!
  26866. stackFillValue: index
  26867.     ^self wbStackValue: index! !
  26868.  
  26869. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 10/30/1998 19:09'!
  26870. stackFillValue: index put: value
  26871.     ^self wbStackValue: index put: value! !
  26872.  
  26873. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 11/24/1998 22:49'!
  26874. topDepth
  26875.     self stackFillSize = 0
  26876.         ifTrue:[^-1]
  26877.         ifFalse:[^self topFillDepth].! !
  26878.  
  26879. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 10/30/1998 19:28'!
  26880. topFill
  26881.     self stackFillSize = 0
  26882.         ifTrue:[^0]
  26883.         ifFalse:[^self topFillValue].! !
  26884.  
  26885. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 10/30/1998 19:27'!
  26886. topFillDepth
  26887.     ^self stackFillDepth: self stackFillSize - self stackFillEntryLength! !
  26888.  
  26889. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 10/30/1998 19:27'!
  26890. topFillDepthPut: value
  26891.     ^self stackFillDepth: self stackFillSize - self stackFillEntryLength put: value! !
  26892.  
  26893. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 11/25/1998 14:36'!
  26894. topFillRightX
  26895.     ^self stackFillRightX: self stackFillSize - self stackFillEntryLength! !
  26896.  
  26897. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 11/25/1998 14:36'!
  26898. topFillRightXPut: value
  26899.     ^self stackFillRightX: self stackFillSize - self stackFillEntryLength put: value! !
  26900.  
  26901. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 10/30/1998 19:27'!
  26902. topFillValue
  26903.     ^self stackFillValue: self stackFillSize - self stackFillEntryLength! !
  26904.  
  26905. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 10/30/1998 19:27'!
  26906. topFillValuePut: value
  26907.     ^self stackFillValue: self stackFillSize - self stackFillEntryLength put: value! !
  26908.  
  26909. !BalloonEngineBase methodsFor: 'accessing fills' stamp: 'ar 11/25/1998 15:19'!
  26910. topRightX
  26911.     self stackFillSize = 0
  26912.         ifTrue:[^999999999]
  26913.         ifFalse:[^self topFillRightX].! !
  26914.  
  26915. !BalloonEngineBase methodsFor: 'loading state' stamp: 'ar 11/24/1998 20:05'!
  26916. loadArrayTransformFrom: transformOop into: destPtr length: n
  26917.     "Load a transformation from the given array."
  26918.     | value |
  26919.     self inline: false.
  26920.     self var: #destPtr declareC:'float *destPtr'.
  26921.     0 to: n-1 do:[:i|
  26922.         value _ interpreterProxy fetchPointer: i ofObject: transformOop.
  26923.         ((interpreterProxy isIntegerObject: value) or:[interpreterProxy isFloatObject: value])
  26924.             ifFalse:[^interpreterProxy primitiveFail].
  26925.         (interpreterProxy isIntegerObject: value)
  26926.             ifTrue:[destPtr at: i put: 
  26927.                 (self cCoerce: (interpreterProxy integerValueOf: value) asFloat to:'float')]
  26928.             ifFalse:[destPtr at: i put: 
  26929.                 (self cCoerce: (interpreterProxy floatValueOf: value) to: 'float')].
  26930.     ].! !
  26931.  
  26932. !BalloonEngineBase methodsFor: 'loading state' stamp: 'ar 11/25/1998 21:04'!
  26933. loadColorTransformFrom: transformOop
  26934.     "Load a 2x3 transformation matrix from the given oop.
  26935.     Return true if the matrix is not nil, false otherwise"
  26936.     | okay transform |
  26937.     self var: #transform declareC:'float *transform'.
  26938.     transform _ self colorTransform.
  26939.     self hasColorTransformPut: 0.
  26940.     okay _ self loadTransformFrom: transformOop into: transform length: 8.
  26941.     okay ifFalse:[^false].
  26942.     self hasColorTransformPut: 1.
  26943.     "Scale transform to be in 0-256 range"
  26944.     transform at: 1 put: (transform at: 1) * (self cCoerce: 256.0 to:'float').
  26945.     transform at: 3 put: (transform at: 3) * (self cCoerce: 256.0 to:'float').
  26946.     transform at: 5 put: (transform at: 5) * (self cCoerce: 256.0 to:'float').
  26947.     transform at: 7 put: (transform at: 7) * (self cCoerce: 256.0 to:'float').
  26948.     ^okay! !
  26949.  
  26950. !BalloonEngineBase methodsFor: 'loading state' stamp: 'ar 11/11/1998 22:21'!
  26951. loadEdgeStateFrom: edgeOop
  26952.     | edge |
  26953.     self inline: false.
  26954.     edge _ self lastExportedEdgeGet.
  26955.     (interpreterProxy slotSizeOf: edgeOop) < ETBalloonEdgeDataSize 
  26956.         ifTrue:[^interpreterProxy primitiveFail].
  26957.     self edgeXValueOf: edge 
  26958.         put: (interpreterProxy fetchInteger: ETXValueIndex ofObject: edgeOop).
  26959.     self edgeYValueOf: edge 
  26960.         put: (interpreterProxy fetchInteger: ETYValueIndex ofObject: edgeOop).
  26961.     self edgeZValueOf: edge 
  26962.         put: (interpreterProxy fetchInteger: ETZValueIndex ofObject: edgeOop).
  26963.     self edgeNumLinesOf: edge 
  26964.         put: (interpreterProxy fetchInteger: ETLinesIndex ofObject: edgeOop).
  26965.     ^edge! !
  26966.  
  26967. !BalloonEngineBase methodsFor: 'loading state' stamp: 'ar 11/24/1998 21:33'!
  26968. loadEdgeTransformFrom: transformOop
  26969.     "Load a 2x3 transformation matrix from the given oop.
  26970.     Return true if the matrix is not nil, false otherwise"
  26971.     | transform okay |
  26972.     self inline: false.
  26973.     self var: #transform declareC:'float *transform'.
  26974.     self hasEdgeTransformPut: 0.
  26975.     transform _ self edgeTransform.
  26976.     okay _ self loadTransformFrom: transformOop into: transform length: 6.
  26977.     interpreterProxy failed ifTrue:[^nil].
  26978.     okay ifFalse:[^false].
  26979.     self hasEdgeTransformPut: 1.
  26980.     "Add the fill offset to the matrix"
  26981.     transform at: 2 put: 
  26982.         (self cCoerce: (transform at: 2) + self destOffsetXGet asFloat to:'float').
  26983.     transform at: 5 put: 
  26984.         (self cCoerce: (transform at: 5) + self destOffsetYGet asFloat to:'float').
  26985.     ^true! !
  26986.  
  26987. !BalloonEngineBase methodsFor: 'loading state' stamp: 'ar 11/25/1998 17:26'!
  26988. loadFormsFrom: arrayOop
  26989.     "Check all the forms from arrayOop."
  26990.     | formOop bmBits bmBitsSize bmWidth bmHeight bmDepth ppw bmRaster |
  26991.     (interpreterProxy fetchClassOf: arrayOop) == interpreterProxy classArray
  26992.         ifFalse:[^false].
  26993.     formArray _ arrayOop.
  26994.     0 to: (interpreterProxy slotSizeOf: formArray) - 1 do:[:i|
  26995.         formOop _ interpreterProxy fetchPointer: i ofObject: formArray.
  26996.         (interpreterProxy isIntegerObject: formOop) ifTrue:[^false].
  26997.         (interpreterProxy isPointers: formOop) ifFalse:[^false].
  26998.         (interpreterProxy slotSizeOf: formOop) < 5 ifTrue:[^false].
  26999.         bmBits _ interpreterProxy fetchPointer: 0 ofObject: formOop.
  27000.         (interpreterProxy fetchClassOf: bmBits) == interpreterProxy classBitmap
  27001.             ifFalse:[^false].
  27002.         bmBitsSize _ interpreterProxy slotSizeOf: bmBits.
  27003.         bmWidth _ interpreterProxy fetchInteger: 1 ofObject: formOop.
  27004.         bmHeight _ interpreterProxy fetchInteger: 2 ofObject: formOop.
  27005.         bmDepth _ interpreterProxy fetchInteger: 3 ofObject: formOop.
  27006.         interpreterProxy failed ifTrue:[^false].
  27007.         (bmWidth >= 0 and:[bmHeight >= 0]) ifFalse:[^false].
  27008.         ppw _ 32 // bmDepth.
  27009.         bmRaster _ bmWidth + (ppw-1) // ppw.
  27010.         bmBitsSize = (bmRaster * bmHeight)
  27011.             ifFalse:[^false].
  27012.     ].
  27013.     ^true! !
  27014.  
  27015. !BalloonEngineBase methodsFor: 'loading state' stamp: 'ar 10/27/1998 21:24'!
  27016. loadPoint: pointArray from: pointOop
  27017.     "Load the contents of pointOop into pointArray"
  27018.     | value |
  27019.     self inline: false.
  27020.     self var: #pointArray declareC:'int *pointArray'.
  27021.     (interpreterProxy fetchClassOf: pointOop) = interpreterProxy classPoint 
  27022.         ifFalse:[^interpreterProxy primitiveFail].
  27023.     value _ interpreterProxy fetchPointer: 0 ofObject: pointOop.
  27024.     ((interpreterProxy isIntegerObject: value) or:[interpreterProxy isFloatObject: value])
  27025.         ifFalse:[^interpreterProxy primitiveFail].
  27026.     (interpreterProxy isIntegerObject: value)
  27027.         ifTrue:[pointArray at: 0 put: (interpreterProxy integerValueOf: value)]
  27028.         ifFalse:[pointArray at: 0 put: (interpreterProxy floatValueOf: value) asInteger].
  27029.     value _ interpreterProxy fetchPointer: 1 ofObject: pointOop.
  27030.     ((interpreterProxy isIntegerObject: value) or:[interpreterProxy isFloatObject: value])
  27031.         ifFalse:[^interpreterProxy primitiveFail].
  27032.     (interpreterProxy isIntegerObject: value)
  27033.         ifTrue:[pointArray at: 1 put: (interpreterProxy integerValueOf: value)]
  27034.         ifFalse:[pointArray at: 1 put: (interpreterProxy floatValueOf: value) asInteger].
  27035. ! !
  27036.  
  27037. !BalloonEngineBase methodsFor: 'loading state' stamp: 'ar 10/28/1998 00:46'!
  27038. loadSpanBufferFrom: spanOop
  27039.     "Load the span buffer from the given oop."
  27040.     self inline: false.
  27041.     (interpreterProxy fetchClassOf: spanOop) = (interpreterProxy classBitmap) ifFalse:[^false].
  27042.     spanBuffer _ interpreterProxy firstIndexableField: spanOop.
  27043.     "Leave last entry unused to avoid complications"
  27044.     self spanSizePut: (interpreterProxy slotSizeOf: spanOop) - 1.
  27045.     ^true! !
  27046.  
  27047. !BalloonEngineBase methodsFor: 'loading state' stamp: 'ar 11/25/1998 23:22'!
  27048. loadTransformFrom: transformOop into: destPtr length: n
  27049.     "Load a transformation from transformOop into the float array
  27050.     defined by destPtr. The transformation is assumed to be either
  27051.     an array or a FloatArray of length n."
  27052.     self inline: false.
  27053.     self var: #destPtr declareC:'float *destPtr'.
  27054.     transformOop = interpreterProxy nilObject ifTrue:[^false].
  27055.     (interpreterProxy isIntegerObject: transformOop)
  27056.         ifTrue:[^interpreterProxy primitiveFail].
  27057.     (interpreterProxy slotSizeOf: transformOop) = n 
  27058.         ifFalse:[^interpreterProxy primitiveFail].
  27059.     (interpreterProxy isWords: transformOop) 
  27060.         ifTrue:[self loadWordTransformFrom: transformOop into: destPtr length: n]
  27061.         ifFalse:[self loadArrayTransformFrom: transformOop into: destPtr length: n].
  27062.     ^true! !
  27063.  
  27064. !BalloonEngineBase methodsFor: 'loading state' stamp: 'ar 11/24/1998 20:03'!
  27065. loadWordTransformFrom: transformOop into: destPtr length: n
  27066.     "Load a float array transformation from the given oop"
  27067.     | srcPtr |
  27068.     self inline: false.
  27069.     self var: #srcPtr declareC:'float *srcPtr'.
  27070.     self var: #destPtr declareC:'float *destPtr'.
  27071.     srcPtr _ self cCoerce: (interpreterProxy firstIndexableField: transformOop) to: 'float *'.
  27072.     0 to: n-1 do:[:i| destPtr at: i put: (srcPtr at: i)].! !
  27073.  
  27074. !BalloonEngineBase methodsFor: 'loading state' stamp: 'ar 10/28/1998 19:37'!
  27075. loadWorkBufferFrom: wbOop
  27076.     "Load the working buffer from the given oop"
  27077.     self inline: false.
  27078.     (interpreterProxy isIntegerObject: wbOop) ifTrue:[^false].
  27079.     (interpreterProxy isWords: wbOop) ifFalse:[^false].
  27080.     (interpreterProxy slotSizeOf: wbOop) < GWMinimalSize ifTrue:[^false].
  27081.     workBuffer _ interpreterProxy firstIndexableField: wbOop.
  27082.     self magicNumberGet = GWMagicNumber ifFalse:[^false].
  27083.     "Sanity checks"
  27084.     (self wbSizeGet = (interpreterProxy slotSizeOf: wbOop)) ifFalse:[^false].
  27085.     self objStartGet = GWHeaderSize ifFalse:[^false].
  27086.  
  27087.     "Load buffers"
  27088.     objBuffer _ workBuffer + self objStartGet.
  27089.     getBuffer _ objBuffer + self objUsedGet.
  27090.     aetBuffer _ getBuffer + self getUsedGet.
  27091.  
  27092.     "Make sure we don't exceed the work buffer"
  27093.     GWHeaderSize + self objUsedGet + self getUsedGet + self aetUsedGet > self wbSizeGet ifTrue:[^false].
  27094.  
  27095.     ^true! !
  27096.  
  27097. !BalloonEngineBase methodsFor: 'loading state' stamp: 'ar 11/25/1998 00:36'!
  27098. quickLoadEngineFrom: engineOop
  27099.     "Load the minimal required state from the engineOop, e.g., just the work buffer."
  27100.     self inline: false.
  27101.     interpreterProxy failed ifTrue:[^false].
  27102.     (interpreterProxy isIntegerObject: engineOop) ifTrue:[^false].
  27103.     (interpreterProxy isPointers: engineOop) ifFalse:[^false].
  27104.     (interpreterProxy slotSizeOf: engineOop) < BEBalloonEngineSize ifTrue:[^false].
  27105.     engine _ engineOop.
  27106.     (self loadWorkBufferFrom: 
  27107.         (interpreterProxy fetchPointer: BEWorkBufferIndex ofObject: engineOop))
  27108.             ifFalse:[^false].
  27109.     self stopReasonPut: 0.
  27110.     objUsed _ self objUsedGet.
  27111.     engineStopped _ false.
  27112.     ^true! !
  27113.  
  27114. !BalloonEngineBase methodsFor: 'loading state' stamp: 'ar 10/28/1998 21:06'!
  27115. quickLoadEngineFrom: oop requiredState: requiredState
  27116.     self inline: false.
  27117.     (self quickLoadEngineFrom: oop) ifFalse:[^false].
  27118.     self stateGet = requiredState ifTrue:[^true].
  27119.     self stopReasonPut: GErrorBadState.
  27120.     ^false! !
  27121.  
  27122. !BalloonEngineBase methodsFor: 'loading state' stamp: 'ar 10/31/1998 17:23'!
  27123. quickLoadEngineFrom: oop requiredState: requiredState or: alternativeState
  27124.     self inline: false.
  27125.     (self quickLoadEngineFrom: oop) ifFalse:[^false].
  27126.     self stateGet = requiredState ifTrue:[^true].
  27127.     self stateGet = alternativeState ifTrue:[^true].
  27128.     self stopReasonPut: GErrorBadState.
  27129.     ^false! !
  27130.  
  27131. !BalloonEngineBase methodsFor: 'storing state' stamp: 'ar 11/11/1998 22:21'!
  27132. storeEdgeStateFrom: edge into: edgeOop
  27133.  
  27134.     self inline: false.
  27135.     (interpreterProxy slotSizeOf: edgeOop) < ETBalloonEdgeDataSize 
  27136.         ifTrue:[^interpreterProxy primitiveFail].
  27137.     interpreterProxy storeInteger: ETIndexIndex ofObject: edgeOop withValue: 
  27138.         (self objectIndexOf: edge).
  27139.     interpreterProxy storeInteger: ETXValueIndex ofObject: edgeOop withValue: 
  27140.         (self edgeXValueOf: edge).
  27141.     interpreterProxy storeInteger: ETYValueIndex ofObject: edgeOop withValue: 
  27142.         (self currentYGet).
  27143.     interpreterProxy storeInteger: ETZValueIndex ofObject: edgeOop withValue: 
  27144.         (self edgeZValueOf: edge).
  27145.     interpreterProxy storeInteger: ETLinesIndex ofObject: edgeOop withValue: 
  27146.         (self edgeNumLinesOf: edge).
  27147.     self lastExportedEdgePut: edge.! !
  27148.  
  27149. !BalloonEngineBase methodsFor: 'storing state' stamp: 'ar 11/25/1998 00:36'!
  27150. storeEngineStateInto: oop
  27151.     self objUsedPut: objUsed.! !
  27152.  
  27153. !BalloonEngineBase methodsFor: 'storing state' stamp: 'ar 11/11/1998 22:24'!
  27154. storeFillStateInto: fillOop
  27155.     | fillIndex leftX rightX |
  27156.     self inline: false.
  27157.     fillIndex _ self lastExportedFillGet.
  27158.     leftX _ self lastExportedLeftXGet.
  27159.     rightX _ self lastExportedRightXGet.
  27160.  
  27161.     (interpreterProxy slotSizeOf: fillOop) < FTBalloonFillDataSize 
  27162.         ifTrue:[^interpreterProxy primitiveFail].
  27163.     interpreterProxy storeInteger: FTIndexIndex ofObject: fillOop withValue: 
  27164.         (self objectIndexOf: fillIndex).
  27165.     interpreterProxy storeInteger: FTMinXIndex ofObject: fillOop withValue: leftX.
  27166.     interpreterProxy storeInteger: FTMaxXIndex ofObject: fillOop withValue: rightX.
  27167.     interpreterProxy storeInteger: FTYValueIndex ofObject: fillOop withValue: self currentYGet.! !
  27168.  
  27169. !BalloonEngineBase methodsFor: 'storing state' stamp: 'ar 11/9/1998 15:34'!
  27170. storeStopStateIntoEdge: edgeOop fill: fillOop
  27171.     | reason edge |
  27172.     reason _ self stopReasonGet.
  27173.  
  27174.     reason = GErrorGETEntry ifTrue:[
  27175.         edge _ getBuffer at: self getStartGet.
  27176.         self storeEdgeStateFrom: edge into: edgeOop.
  27177.         self getStartPut: self getStartGet + 1.
  27178.     ].
  27179.  
  27180.     reason = GErrorFillEntry ifTrue:[
  27181.         self storeFillStateInto: fillOop.
  27182.     ].
  27183.  
  27184.     reason = GErrorAETEntry ifTrue:[
  27185.         edge _ aetBuffer at: self aetStartGet.
  27186.         self storeEdgeStateFrom: edge into: edgeOop.
  27187.         "Do not advance to the next aet entry yet"
  27188.         "self aetStartPut: self aetStartGet + 1."
  27189.     ].! !
  27190.  
  27191. !BalloonEngineBase methodsFor: 'testing' stamp: 'ar 11/9/1998 15:34'!
  27192. areEdgeFillsValid: edge
  27193.  
  27194.     ^((self objectHeaderOf: edge) bitAnd: GEEdgeFillsInvalid) = 0! !
  27195.  
  27196. !BalloonEngineBase methodsFor: 'testing' stamp: 'ar 10/31/1998 17:06'!
  27197. finishedProcessing
  27198.     "Return true if processing is finished"
  27199.     ^self stateGet = GEStateCompleted! !
  27200.  
  27201. !BalloonEngineBase methodsFor: 'testing' stamp: 'ar 11/24/1998 19:39'!
  27202. hasColorTransform
  27203.     ^self hasColorTransformGet ~= 0! !
  27204.  
  27205. !BalloonEngineBase methodsFor: 'testing' stamp: 'ar 11/24/1998 19:38'!
  27206. hasEdgeTransform
  27207.     ^self hasEdgeTransformGet ~= 0! !
  27208.  
  27209. !BalloonEngineBase methodsFor: 'testing' stamp: 'ar 10/29/1998 19:36'!
  27210. isEdge: edge
  27211.     | type |
  27212.     type _ self objectTypeOf: edge.
  27213.     type > GEPrimitiveEdgeMask ifTrue:[^false].
  27214.     ^((self objectTypeOf: edge) bitAnd: GEPrimitiveEdgeMask) ~= 0! !
  27215.  
  27216. !BalloonEngineBase methodsFor: 'testing' stamp: 'ar 11/7/1998 21:28'!
  27217. isFill: fill
  27218.     ^(self isFillColor: fill) or:[self isRealFill: fill]! !
  27219.  
  27220. !BalloonEngineBase methodsFor: 'testing' stamp: 'ar 10/29/1998 19:31'!
  27221. isFillColor: fill
  27222.     ^((self makeUnsignedFrom: fill) bitAnd: 16rFF000000) ~= 0! !
  27223.  
  27224. !BalloonEngineBase methodsFor: 'testing' stamp: 'ar 11/25/1998 00:43'!
  27225. isObject: obj
  27226.     ^obj >= 0 and:[obj < objUsed]! !
  27227.  
  27228. !BalloonEngineBase methodsFor: 'testing' stamp: 'ar 11/7/1998 21:28'!
  27229. isRealFill: fill
  27230.     ^((self objectTypeOf: fill) bitAnd: GEPrimitiveFillMask) ~= 0! !
  27231.  
  27232. !BalloonEngineBase methodsFor: 'testing' stamp: 'ar 10/31/1998 23:12'!
  27233. isStackEntry: entry
  27234.     ^entry >= self wbTopGet and:[entry < self wbSizeGet]! !
  27235.  
  27236. !BalloonEngineBase methodsFor: 'testing' stamp: 'ar 10/30/1998 17:38'!
  27237. isStackIndex: index
  27238.     ^index >= 0 and:[index < self wbStackSize]! !
  27239.  
  27240. !BalloonEngineBase methodsFor: 'testing' stamp: 'ar 11/9/1998 15:36'!
  27241. isWide: object
  27242.  
  27243.     ^((self objectTypeOf: object) bitAnd: GEPrimitiveWide) ~= 0! !
  27244.  
  27245. !BalloonEngineBase methodsFor: 'testing' stamp: 'ar 11/25/1998 00:21'!
  27246. needsFlush
  27247.     ^self needsFlushGet ~= 0! !
  27248.  
  27249. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:08'!
  27250. primitiveGetAALevel
  27251.     self export: true.    
  27252.     self inline: false.
  27253.     interpreterProxy methodArgumentCount = 0
  27254.         ifFalse:[^interpreterProxy primitiveFail].
  27255.     engine _ interpreterProxy stackObjectValue: 0.
  27256.     interpreterProxy failed ifTrue:[^nil].
  27257.     (self quickLoadEngineFrom: engine)
  27258.         ifFalse:[^interpreterProxy primitiveFail].
  27259.     interpreterProxy pop: 1.
  27260.     interpreterProxy pushInteger: self aaLevelGet.! !
  27261.  
  27262. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:10'!
  27263. primitiveGetClipRect
  27264.     | rectOop pointOop |
  27265.     self export: true.    
  27266.     self inline: false.
  27267.  
  27268.     interpreterProxy methodArgumentCount = 1
  27269.         ifFalse:[^interpreterProxy primitiveFail].
  27270.  
  27271.     rectOop _ interpreterProxy stackObjectValue: 0.
  27272.     engine _ interpreterProxy stackObjectValue: 1.
  27273.     interpreterProxy failed ifTrue:[^nil].
  27274.     (self quickLoadEngineFrom: engine)
  27275.         ifFalse:[^interpreterProxy primitiveFail].
  27276.  
  27277.     (interpreterProxy isPointers: rectOop)
  27278.         ifFalse:[^interpreterProxy primitiveFail].
  27279.     (interpreterProxy slotSizeOf: rectOop) < 2
  27280.         ifTrue:[^interpreterProxy primitiveFail].
  27281.  
  27282.     interpreterProxy pushRemappableOop: rectOop.
  27283.     pointOop _ interpreterProxy makePointwithxValue: self clipMinXGet yValue: self clipMinYGet.
  27284.     rectOop _ interpreterProxy popRemappableOop.
  27285.     interpreterProxy storePointer: 0 ofObject: rectOop withValue: pointOop.
  27286.     interpreterProxy pushRemappableOop: rectOop.
  27287.     pointOop _ interpreterProxy makePointwithxValue: self clipMaxXGet yValue: self clipMaxYGet.
  27288.     rectOop _ interpreterProxy popRemappableOop.
  27289.     interpreterProxy storePointer: 1 ofObject: rectOop withValue: pointOop.
  27290.  
  27291.     interpreterProxy pop: 2.
  27292.     interpreterProxy push: rectOop.! !
  27293.  
  27294. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:13'!
  27295. primitiveGetCounts
  27296.     | statOop stats |
  27297.     self export: true.
  27298.     self inline: false.
  27299.     self var: #stats declareC:'int *stats'.
  27300.  
  27301.     interpreterProxy methodArgumentCount = 1
  27302.         ifFalse:[^interpreterProxy primitiveFail].
  27303.  
  27304.     statOop _ interpreterProxy stackObjectValue: 0.
  27305.     engine _ interpreterProxy stackObjectValue: 1.
  27306.     interpreterProxy failed ifTrue:[^nil].
  27307.     (self quickLoadEngineFrom: engine)
  27308.         ifFalse:[^interpreterProxy primitiveFail].
  27309.  
  27310.     (interpreterProxy isWords: statOop)
  27311.         ifFalse:[^interpreterProxy primitiveFail].
  27312.     (interpreterProxy slotSizeOf: statOop) < 9
  27313.         ifTrue:[^interpreterProxy primitiveFail].
  27314.     stats _ interpreterProxy firstIndexableField: statOop.
  27315.     stats at: 0 put: (stats at: 0) + (workBuffer at: GWCountInitializing).
  27316.     stats at: 1 put: (stats at: 1) + (workBuffer at: GWCountFinishTest).
  27317.     stats at: 2 put: (stats at: 2) + (workBuffer at: GWCountNextGETEntry).
  27318.     stats at: 3 put: (stats at: 3) + (workBuffer at: GWCountAddAETEntry).
  27319.     stats at: 4 put: (stats at: 4) + (workBuffer at: GWCountNextFillEntry).
  27320.     stats at: 5 put: (stats at: 5) + (workBuffer at: GWCountMergeFill).
  27321.     stats at: 6 put: (stats at: 6) + (workBuffer at: GWCountDisplaySpan).
  27322.     stats at: 7 put: (stats at: 7) + (workBuffer at: GWCountNextAETEntry).
  27323.     stats at: 8 put: (stats at: 8) + (workBuffer at: GWCountChangeAETEntry).
  27324.  
  27325.     interpreterProxy pop: 1. "Leave rcvr on stack"! !
  27326.  
  27327. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:14'!
  27328. primitiveGetDepth
  27329.     self export: true.    
  27330.     self inline: false.
  27331.     interpreterProxy methodArgumentCount = 0
  27332.         ifFalse:[^interpreterProxy primitiveFail].
  27333.     engine _ interpreterProxy stackObjectValue: 0.
  27334.     interpreterProxy failed ifTrue:[^nil].
  27335.     (self quickLoadEngineFrom: engine)
  27336.         ifFalse:[^interpreterProxy primitiveFail].
  27337.     interpreterProxy pop: 1.
  27338.     interpreterProxy pushInteger: self currentZGet.! !
  27339.  
  27340. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:10'!
  27341. primitiveGetFailureReason
  27342.     "Return the reason why the last operation failed."
  27343.     self export: true.    
  27344.     self inline: false.
  27345.     interpreterProxy methodArgumentCount = 0
  27346.         ifFalse:[^interpreterProxy primitiveFail].
  27347.     engine _ interpreterProxy stackObjectValue: 0.
  27348.     interpreterProxy failed ifTrue:[^nil].
  27349.     "Note -- don't call loadEngineFrom here because this will override the stopReason with Zero"
  27350.     (interpreterProxy isIntegerObject: engine) ifTrue:[^false].
  27351.     (interpreterProxy isPointers: engine) ifFalse:[^false].
  27352.     (interpreterProxy slotSizeOf: engine) < BEBalloonEngineSize ifTrue:[^false].
  27353.     (self loadWorkBufferFrom: 
  27354.         (interpreterProxy fetchPointer: BEWorkBufferIndex ofObject: engine))
  27355.             ifFalse:[^interpreterProxy primitiveFail].
  27356.     interpreterProxy pop: 1.
  27357.     interpreterProxy pushInteger: self stopReasonGet.! !
  27358.  
  27359. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:11'!
  27360. primitiveGetOffset
  27361.     | pointOop |
  27362.     self export: true.    
  27363.     self inline: false.
  27364.  
  27365.     interpreterProxy methodArgumentCount = 0
  27366.         ifFalse:[^interpreterProxy primitiveFail].
  27367.  
  27368.     engine _ interpreterProxy stackObjectValue: 0.
  27369.     interpreterProxy failed ifTrue:[^nil].
  27370.     (self quickLoadEngineFrom: engine)
  27371.         ifFalse:[^interpreterProxy primitiveFail].
  27372.     pointOop _ interpreterProxy makePointwithxValue: self destOffsetXGet yValue: self destOffsetYGet.
  27373.     interpreterProxy pop: 1.
  27374.     interpreterProxy push: pointOop.! !
  27375.  
  27376. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:07'!
  27377. primitiveGetTimes
  27378.     | statOop stats |
  27379.     self export: true.
  27380.     self inline: false.
  27381.     self var: #stats declareC:'int *stats'.
  27382.  
  27383.     interpreterProxy methodArgumentCount = 1
  27384.         ifFalse:[^interpreterProxy primitiveFail].
  27385.  
  27386.     statOop _ interpreterProxy stackObjectValue: 0.
  27387.     engine _ interpreterProxy stackObjectValue: 1.
  27388.     interpreterProxy failed ifTrue:[^nil].
  27389.     (self quickLoadEngineFrom: engine)
  27390.         ifFalse:[^interpreterProxy primitiveFail].
  27391.  
  27392.     (interpreterProxy isWords: statOop)
  27393.         ifFalse:[^interpreterProxy primitiveFail].
  27394.     (interpreterProxy slotSizeOf: statOop) < 9
  27395.         ifTrue:[^interpreterProxy primitiveFail].
  27396.     stats _ interpreterProxy firstIndexableField: statOop.
  27397.     stats at: 0 put: (stats at: 0) + (workBuffer at: GWTimeInitializing).
  27398.     stats at: 1 put: (stats at: 1) + (workBuffer at: GWTimeFinishTest).
  27399.     stats at: 2 put: (stats at: 2) + (workBuffer at: GWTimeNextGETEntry).
  27400.     stats at: 3 put: (stats at: 3) + (workBuffer at: GWTimeAddAETEntry).
  27401.     stats at: 4 put: (stats at: 4) + (workBuffer at: GWTimeNextFillEntry).
  27402.     stats at: 5 put: (stats at: 5) + (workBuffer at: GWTimeMergeFill).
  27403.     stats at: 6 put: (stats at: 6) + (workBuffer at: GWTimeDisplaySpan).
  27404.     stats at: 7 put: (stats at: 7) + (workBuffer at: GWTimeNextAETEntry).
  27405.     stats at: 8 put: (stats at: 8) + (workBuffer at: GWTimeChangeAETEntry).
  27406.  
  27407.     interpreterProxy pop: 1. "Leave rcvr on stack"! !
  27408.  
  27409. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:12'!
  27410. primitiveNeedsFlush
  27411.     | needFlush |
  27412.     self export: true.
  27413.     self inline: false.
  27414.     interpreterProxy methodArgumentCount = 0
  27415.         ifFalse:[^interpreterProxy primitiveFail].
  27416.     engine _ interpreterProxy stackObjectValue: 0.
  27417.     interpreterProxy failed ifTrue:[^nil].
  27418.     (self quickLoadEngineFrom: engine)
  27419.         ifFalse:[^interpreterProxy primitiveFail].
  27420.     needFlush _ self needsFlush.
  27421.     self storeEngineStateInto: engine.
  27422.     interpreterProxy pop: 1.
  27423.     interpreterProxy pushBool: needFlush.
  27424.  
  27425. ! !
  27426.  
  27427. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:14'!
  27428. primitiveNeedsFlushPut
  27429.     | needFlush |
  27430.     self export: true.
  27431.     self inline: false.
  27432.     interpreterProxy methodArgumentCount = 1
  27433.         ifFalse:[^interpreterProxy primitiveFail].
  27434.     needFlush _ interpreterProxy stackObjectValue: 0.
  27435.     engine _ interpreterProxy stackObjectValue: 1.
  27436.     interpreterProxy failed ifTrue:[^nil].
  27437.     needFlush _ interpreterProxy booleanValueOf: needFlush.
  27438.     interpreterProxy failed ifTrue:[^nil].
  27439.     (self quickLoadEngineFrom: engine)
  27440.         ifFalse:[^interpreterProxy primitiveFail].
  27441.     needFlush == true 
  27442.         ifTrue:[self needsFlushPut: 1]
  27443.         ifFalse:[self needsFlushPut: 0].
  27444.     self storeEngineStateInto: engine.
  27445.     interpreterProxy pop: 1. "Leave rcvr on stack"
  27446. ! !
  27447.  
  27448. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:12'!
  27449. primitiveSetAALevel
  27450.     | level |
  27451.     self export: true.
  27452.     self inline: false.
  27453.     interpreterProxy methodArgumentCount = 1
  27454.         ifFalse:[^interpreterProxy primitiveFail].
  27455.     level _ interpreterProxy stackIntegerValue: 0.
  27456.     engine _ interpreterProxy stackObjectValue: 1.
  27457.     interpreterProxy failed ifTrue:[^nil].
  27458.     (self quickLoadEngineFrom: engine requiredState: GEStateUnlocked)
  27459.         ifFalse:[^interpreterProxy primitiveFail].
  27460.     self setAALevel: level.
  27461.     self storeEngineStateInto: engine.
  27462.     interpreterProxy pop: 1. "Leace rcvr on stack"! !
  27463.  
  27464. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/16/2000 20:03'!
  27465. primitiveSetBitBltPlugin
  27466.     "Primitive. Set the BitBlt plugin to use."
  27467.     | pluginName length ptr needReload |
  27468.     self export: true.
  27469.     self var: #ptr declareC:'char *ptr'.
  27470.     pluginName _ interpreterProxy stackValue: 0.
  27471.     "Must be string to work"
  27472.     (interpreterProxy isBytes: pluginName) 
  27473.         ifFalse:[^interpreterProxy primitiveFail].
  27474.     length _ interpreterProxy byteSizeOf: pluginName.
  27475.     length >= 256 
  27476.         ifTrue:[^interpreterProxy primitiveFail].
  27477.     ptr _ interpreterProxy firstIndexableField: pluginName.
  27478.     needReload _ false.
  27479.     0 to: length-1 do:[:i|
  27480.         "Compare and store the plugin to be used"
  27481.         (bbPluginName at: i) = (ptr at: i) ifFalse:[
  27482.             bbPluginName at: i put: (ptr at: i).
  27483.             needReload _ true]].
  27484.     (bbPluginName at: length) = 0 ifFalse:[
  27485.         bbPluginName at: length put: 0.
  27486.         needReload _ true].
  27487.     needReload ifTrue:[
  27488.         self initialiseModule 
  27489.             ifFalse:[^interpreterProxy primitiveFail]].
  27490.     interpreterProxy pop: 1. "Return receiver"! !
  27491.  
  27492. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:05'!
  27493. primitiveSetClipRect
  27494.     | rectOop |
  27495.     self export: true.    
  27496.     self inline: false.
  27497.  
  27498.     interpreterProxy methodArgumentCount = 1
  27499.         ifFalse:[^interpreterProxy primitiveFail].
  27500.  
  27501.     rectOop _ interpreterProxy stackObjectValue: 0.
  27502.     engine _ interpreterProxy stackObjectValue: 1.
  27503.     interpreterProxy failed ifTrue:[^nil].
  27504.     (self quickLoadEngineFrom: engine requiredState: GEStateUnlocked)
  27505.         ifFalse:[^interpreterProxy primitiveFail].
  27506.  
  27507.     (interpreterProxy isPointers: rectOop)
  27508.         ifFalse:[^interpreterProxy primitiveFail].
  27509.     (interpreterProxy slotSizeOf: rectOop) < 2
  27510.         ifTrue:[^interpreterProxy primitiveFail].
  27511.     self loadPoint: self point1Get from: (interpreterProxy fetchPointer: 0 ofObject: rectOop).
  27512.     self loadPoint: self point2Get from: (interpreterProxy fetchPointer: 1 ofObject: rectOop).
  27513.     interpreterProxy failed ifFalse:[
  27514.         self clipMinXPut: (self point1Get at: 0).
  27515.         self clipMinYPut: (self point1Get at: 1).
  27516.         self clipMaxXPut: (self point2Get at: 0).
  27517.         self clipMaxYPut: (self point2Get at: 1).
  27518.         self storeEngineStateInto: engine.
  27519.         interpreterProxy pop: 1. "Leave rcvr on stack"
  27520.     ].! !
  27521.  
  27522. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:11'!
  27523. primitiveSetColorTransform
  27524.     | transformOop |
  27525.     self export: true.    
  27526.     self inline: false.
  27527.  
  27528.     interpreterProxy methodArgumentCount = 1
  27529.         ifFalse:[^interpreterProxy primitiveFail].
  27530.  
  27531.     transformOop _ interpreterProxy stackObjectValue: 0.
  27532.     engine _ interpreterProxy stackObjectValue: 1.
  27533.     interpreterProxy failed ifTrue:[^nil].
  27534.     (self quickLoadEngineFrom: engine requiredState: GEStateUnlocked)
  27535.         ifFalse:[^interpreterProxy primitiveFail].
  27536.  
  27537.     self loadColorTransformFrom: transformOop.
  27538.     interpreterProxy failed ifFalse:[
  27539.         self storeEngineStateInto: engine.
  27540.         interpreterProxy pop: 1. "Leave rcvr on stack"
  27541.     ].! !
  27542.  
  27543. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:06'!
  27544. primitiveSetDepth
  27545.     | depth |
  27546.     self export: true.    
  27547.     self inline: false.
  27548.  
  27549.     interpreterProxy methodArgumentCount = 1
  27550.         ifFalse:[^interpreterProxy primitiveFail].
  27551.  
  27552.     depth _ interpreterProxy stackIntegerValue: 0.
  27553.     engine _ interpreterProxy stackObjectValue: 1.
  27554.     interpreterProxy failed ifTrue:[^nil].
  27555.     (self quickLoadEngineFrom: engine requiredState: GEStateUnlocked)
  27556.         ifFalse:[^interpreterProxy primitiveFail].
  27557.  
  27558.     self currentZPut: depth.
  27559.  
  27560.     interpreterProxy failed ifFalse:[
  27561.         self storeEngineStateInto: engine.
  27562.         interpreterProxy pop: 1. "Leave rcvr on stack"
  27563.     ].! !
  27564.  
  27565. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:14'!
  27566. primitiveSetEdgeTransform
  27567.     | transformOop |
  27568.     self export: true.    
  27569.     self inline: false.
  27570.  
  27571.     interpreterProxy methodArgumentCount = 1
  27572.         ifFalse:[^interpreterProxy primitiveFail].
  27573.  
  27574.     transformOop _ interpreterProxy stackObjectValue: 0.
  27575.     engine _ interpreterProxy stackObjectValue: 1.
  27576.     interpreterProxy failed ifTrue:[^nil].
  27577.     (self quickLoadEngineFrom: engine requiredState: GEStateUnlocked)
  27578.         ifFalse:[^interpreterProxy primitiveFail].
  27579.  
  27580.     self loadEdgeTransformFrom: transformOop.
  27581.     interpreterProxy failed ifFalse:[
  27582.         self storeEngineStateInto: engine.
  27583.         interpreterProxy pop: 1. "Leave rcvr on stack"
  27584.     ].! !
  27585.  
  27586. !BalloonEngineBase methodsFor: 'primitives-access' stamp: 'ar 5/11/2000 23:13'!
  27587. primitiveSetOffset
  27588.     | pointOop |
  27589.     self export: true.    
  27590.     self inline: false.
  27591.  
  27592.     interpreterProxy methodArgumentCount = 1
  27593.         ifFalse:[^interpreterProxy primitiveFail].
  27594.  
  27595.     pointOop _ interpreterProxy stackObjectValue: 0.
  27596.     engine _ interpreterProxy stackObjectValue: 1.
  27597.     interpreterProxy failed ifTrue:[^nil].
  27598.     (self quickLoadEngineFrom: engine requiredState: GEStateUnlocked)
  27599.         ifFalse:[^interpreterProxy primitiveFail].
  27600.     (interpreterProxy fetchClassOf: pointOop) = interpreterProxy classPoint
  27601.         ifFalse:[^interpreterProxy primitiveFail].
  27602.     self loadPoint: self point1Get from: pointOop.
  27603.     interpreterProxy failed ifFalse:[
  27604.         self destOffsetXPut: (self point1Get at: 0).
  27605.         self destOffsetYPut: (self point1Get at: 1).
  27606.         self storeEngineStateInto: engine.
  27607.         interpreterProxy pop: 1. "Leave rcvr on stack"
  27608.     ].! !
  27609.  
  27610. !BalloonEngineBase methodsFor: 'primitives-incremental' stamp: 'ar 5/13/2000 14:58'!
  27611. primitiveAddActiveEdgeEntry
  27612.     "Note: No need to load either bitBlt or spanBuffer"
  27613.     | edgeOop edge |
  27614.     self export: true.
  27615.     self inline: false.
  27616.     doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  27617.     interpreterProxy methodArgumentCount = 1
  27618.         ifFalse:[^interpreterProxy primitiveFail].
  27619.     edgeOop _ interpreterProxy stackObjectValue: 0.
  27620.     engine _ interpreterProxy stackObjectValue: 1.
  27621.     interpreterProxy failed ifTrue:[^nil].
  27622.     (self quickLoadEngineFrom: engine requiredState: GEStateWaitingForEdge)
  27623.         ifFalse:[^interpreterProxy primitiveFail].
  27624.  
  27625.     edge _ self loadEdgeStateFrom: edgeOop.
  27626.     interpreterProxy failed ifTrue:[^nil].
  27627.  
  27628.     (self needAvailableSpace: 1) 
  27629.         ifFalse:[^interpreterProxy primitiveFail].
  27630.  
  27631.     (self edgeNumLinesOf: edge) > 0 ifTrue:[
  27632.         self insertEdgeIntoAET: edge.
  27633.     ].
  27634.  
  27635.     engineStopped ifTrue:[^interpreterProxy primitiveFail].
  27636.  
  27637.     self statePut: GEStateAddingFromGET. "Back to adding edges from GET"
  27638.     self storeEngineStateInto: engine.
  27639.     interpreterProxy pop: 1. "Leave rcvr on stack"
  27640.     doProfileStats ifTrue:[
  27641.         self incrementStat: GWCountAddAETEntry by: 1.
  27642.         self incrementStat: GWTimeAddAETEntry by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  27643. ! !
  27644.  
  27645. !BalloonEngineBase methodsFor: 'primitives-incremental' stamp: 'ar 5/13/2000 14:59'!
  27646. primitiveChangedActiveEdgeEntry
  27647.     "Note: No need to load either bitBlt or spanBuffer"
  27648.     | edgeOop edge |
  27649.     self export: true.
  27650.     self inline: false.
  27651.     doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  27652.     interpreterProxy methodArgumentCount = 1
  27653.         ifFalse:[^interpreterProxy primitiveFail].
  27654.     edgeOop _ interpreterProxy stackObjectValue: 0.
  27655.     engine _ interpreterProxy stackObjectValue: 1.
  27656.     interpreterProxy failed ifTrue:[^nil].
  27657.     (self quickLoadEngineFrom: engine requiredState: GEStateWaitingChange)
  27658.         ifFalse:[^interpreterProxy primitiveFail].
  27659.  
  27660.     edge _ self loadEdgeStateFrom: edgeOop.
  27661.     interpreterProxy failed ifTrue:[^nil].
  27662.  
  27663.     (self edgeNumLinesOf: edge) = 0 
  27664.         ifTrue:[    self removeFirstAETEntry]
  27665.         ifFalse:[    self resortFirstAETEntry.
  27666.                 self aetStartPut: self aetStartGet + 1].
  27667.  
  27668.     self statePut: GEStateUpdateEdges. "Back to updating edges"
  27669.     self storeEngineStateInto: engine.
  27670.     interpreterProxy pop: 1. "Leave rcvr on stack"
  27671.     doProfileStats ifTrue:[
  27672.         self incrementStat: GWCountChangeAETEntry by: 1.
  27673.         self incrementStat: GWTimeChangeAETEntry by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  27674. ! !
  27675.  
  27676. !BalloonEngineBase methodsFor: 'primitives-incremental' stamp: 'ar 5/13/2000 14:59'!
  27677. primitiveDisplaySpanBuffer
  27678.     "Note: Must load bitBlt and spanBuffer"
  27679.     self export: true.
  27680.     self inline: false.
  27681.     doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  27682.     interpreterProxy methodArgumentCount = 0
  27683.         ifFalse:[^interpreterProxy primitiveFail].
  27684.     engine _ interpreterProxy stackObjectValue: 0.
  27685.     interpreterProxy failed ifTrue:[^nil].
  27686.     (self quickLoadEngineFrom: engine requiredState: GEStateBlitBuffer)
  27687.         ifFalse:[^interpreterProxy primitiveFail].
  27688.     "Load span buffer and bitBlt"
  27689.     (self loadSpanBufferFrom:
  27690.         (interpreterProxy fetchPointer: BESpanIndex ofObject: engine))
  27691.             ifFalse:[^interpreterProxy primitiveFail].
  27692.     (self loadBitBltFrom: 
  27693.         (interpreterProxy fetchPointer: BEBitBltIndex ofObject: engine))
  27694.             ifFalse:[^interpreterProxy primitiveFail].
  27695.     (self currentYGet bitAnd: self aaScanMaskGet) = self aaScanMaskGet ifTrue:[
  27696.         self displaySpanBufferAt: self currentYGet.
  27697.         self postDisplayAction.
  27698.     ].
  27699.     self finishedProcessing ifFalse:[
  27700.         self aetStartPut: 0.
  27701.         self currentYPut: self currentYGet + 1.
  27702.         self statePut: GEStateUpdateEdges].
  27703.     self storeEngineStateInto: engine.
  27704.     doProfileStats ifTrue:[
  27705.         self incrementStat: GWCountDisplaySpan by: 1.
  27706.         self incrementStat: GWTimeDisplaySpan by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  27707. ! !
  27708.  
  27709. !BalloonEngineBase methodsFor: 'primitives-incremental' stamp: 'ar 5/13/2000 14:59'!
  27710. primitiveInitializeProcessing
  27711.     "Note: No need to load bitBlt but must load spanBuffer"
  27712.     self export: true.
  27713.     self inline: false.
  27714.     doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  27715.     interpreterProxy methodArgumentCount = 0
  27716.         ifFalse:[^interpreterProxy primitiveFail].
  27717.     engine _ interpreterProxy stackObjectValue: 0.
  27718.     interpreterProxy failed ifTrue:[^nil].
  27719.     (self quickLoadEngineFrom: engine requiredState: GEStateUnlocked) 
  27720.         ifFalse:[^interpreterProxy primitiveFail].
  27721.     "Load span buffer for clear operation"
  27722.     (self loadSpanBufferFrom:
  27723.         (interpreterProxy fetchPointer: BESpanIndex ofObject: engine))
  27724.             ifFalse:[^interpreterProxy primitiveFail].
  27725.     self initializeGETProcessing.
  27726.     engineStopped ifTrue:[^interpreterProxy primitiveFail].
  27727.     self statePut: GEStateAddingFromGET. "Initialized"
  27728.     interpreterProxy failed ifFalse:[self storeEngineStateInto: engine].
  27729.     doProfileStats ifTrue:[
  27730.         self incrementStat: GWCountInitializing by: 1.
  27731.         self incrementStat: GWTimeInitializing by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  27732. ! !
  27733.  
  27734. !BalloonEngineBase methodsFor: 'primitives-incremental' stamp: 'ar 5/13/2000 14:59'!
  27735. primitiveMergeFillFrom
  27736.     "Note: No need to load bitBlt but must load spanBuffer"
  27737.     | fillOop bitsOop value |
  27738.     self export: true.
  27739.     self inline: false.
  27740.     doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  27741.     interpreterProxy methodArgumentCount = 2
  27742.         ifFalse:[^interpreterProxy primitiveFail].
  27743.     fillOop _ interpreterProxy stackObjectValue: 0.
  27744.     bitsOop _ interpreterProxy stackObjectValue: 1.
  27745.     engine _ interpreterProxy stackObjectValue: 2.
  27746.     interpreterProxy failed ifTrue:[^nil].
  27747.     (self quickLoadEngineFrom: engine requiredState: GEStateWaitingForFill)
  27748.         ifFalse:[^interpreterProxy primitiveFail].
  27749.     "Load span buffer for merging the fill"
  27750.     (self loadSpanBufferFrom:
  27751.         (interpreterProxy fetchPointer: BESpanIndex ofObject: engine))
  27752.             ifFalse:[^interpreterProxy primitiveFail].
  27753.     "Check bitmap"
  27754.     (interpreterProxy fetchClassOf: bitsOop) = interpreterProxy classBitmap
  27755.         ifFalse:[^interpreterProxy primitiveFail].
  27756.     "Check fillOop"
  27757.     (interpreterProxy slotSizeOf: fillOop) < FTBalloonFillDataSize
  27758.         ifTrue:[^interpreterProxy primitiveFail].
  27759.     "Check if this was the fill we have exported"
  27760.     value _ interpreterProxy fetchInteger: FTIndexIndex ofObject: fillOop.
  27761.     (self objectIndexOf: self lastExportedFillGet) = value
  27762.         ifFalse:[^interpreterProxy primitiveFail].
  27763.     value _ interpreterProxy fetchInteger: FTMinXIndex ofObject: fillOop.
  27764.     self lastExportedLeftXGet = value
  27765.         ifFalse:[^interpreterProxy primitiveFail].
  27766.     value _ interpreterProxy fetchInteger: FTMaxXIndex ofObject: fillOop.
  27767.     self lastExportedRightXGet = value
  27768.         ifFalse:[^interpreterProxy primitiveFail].
  27769.  
  27770.     (interpreterProxy slotSizeOf: bitsOop) < (self lastExportedRightXGet - self lastExportedLeftXGet)
  27771.         ifTrue:[^interpreterProxy primitiveFail].
  27772.  
  27773.     interpreterProxy failed ifTrue:[^nil].
  27774.  
  27775.     self fillBitmapSpan: (interpreterProxy firstIndexableField: bitsOop)
  27776.         from: self lastExportedLeftXGet
  27777.         to: self lastExportedRightXGet.
  27778.  
  27779.     self statePut: GEStateScanningAET. "Back to scanning AET"
  27780.     self storeEngineStateInto: engine.
  27781.     interpreterProxy pop: 2. "Leave rcvr on stack"
  27782.     doProfileStats ifTrue:[
  27783.         self incrementStat: GWCountMergeFill by: 1.
  27784.         self incrementStat: GWTimeMergeFill by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  27785. ! !
  27786.  
  27787. !BalloonEngineBase methodsFor: 'primitives-incremental' stamp: 'ar 5/13/2000 14:59'!
  27788. primitiveNextActiveEdgeEntry
  27789.     "Note: No need to load either bitBlt or spanBuffer"
  27790.     | edgeOop hasEdge edge |
  27791.     self export: true.
  27792.     self inline: false.
  27793.     doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  27794.     interpreterProxy methodArgumentCount = 1
  27795.         ifFalse:[^interpreterProxy primitiveFail].
  27796.     edgeOop _ interpreterProxy stackObjectValue: 0.
  27797.     engine _ interpreterProxy stackObjectValue: 1.
  27798.     interpreterProxy failed ifTrue:[^nil].
  27799.     (self quickLoadEngineFrom: engine requiredState: GEStateUpdateEdges or: GEStateCompleted)
  27800.         ifFalse:[^interpreterProxy primitiveFail].
  27801.  
  27802.     hasEdge _ false.
  27803.     self stateGet = GEStateCompleted ifFalse:[
  27804.         hasEdge _ self findNextExternalUpdateFromAET.
  27805.         hasEdge ifTrue:[
  27806.             edge _ aetBuffer at: self aetStartGet.
  27807.             self storeEdgeStateFrom: edge into: edgeOop.
  27808.             "Do not advance to the next aet entry yet"
  27809.             "self aetStartPut: self aetStartGet + 1."
  27810.             self statePut: GEStateWaitingChange. "Wait for changed edge"
  27811.         ] ifFalse:[self statePut: GEStateAddingFromGET]. "Start over"
  27812.     ].
  27813.     interpreterProxy failed ifTrue:[^nil].
  27814.  
  27815.     self storeEngineStateInto: engine.
  27816.  
  27817.     interpreterProxy pop: 2.
  27818.     interpreterProxy pushBool: hasEdge not.
  27819.     doProfileStats ifTrue:[
  27820.         self incrementStat: GWCountNextAETEntry by: 1.
  27821.         self incrementStat: GWTimeNextAETEntry by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  27822. ! !
  27823.  
  27824. !BalloonEngineBase methodsFor: 'primitives-incremental' stamp: 'ar 5/13/2000 14:59'!
  27825. primitiveNextFillEntry
  27826.     "Note: No need to load bitBlt but must load spanBuffer"
  27827.     | fillOop hasFill |
  27828.     self export: true.
  27829.     self inline: false.
  27830.     doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  27831.     interpreterProxy methodArgumentCount = 1
  27832.         ifFalse:[^interpreterProxy primitiveFail].
  27833.     fillOop _ interpreterProxy stackObjectValue: 0.
  27834.     engine _ interpreterProxy stackObjectValue: 1.
  27835.     interpreterProxy failed ifTrue:[^nil].
  27836.     (self quickLoadEngineFrom: engine requiredState: GEStateScanningAET)
  27837.         ifFalse:[^interpreterProxy primitiveFail].
  27838.     "Load span buffer for internal handling of fills"
  27839.     (self loadSpanBufferFrom:
  27840.         (interpreterProxy fetchPointer: BESpanIndex ofObject: engine))
  27841.             ifFalse:[^interpreterProxy primitiveFail].
  27842.     (self loadFormsFrom:
  27843.         (interpreterProxy fetchPointer: BEFormsIndex ofObject: engine))
  27844.             ifFalse:[^interpreterProxy primitiveFail].
  27845.  
  27846.     "Check if we have to clear the span buffer before proceeding"
  27847.     (self clearSpanBufferGet = 0) ifFalse:[
  27848.         (self currentYGet bitAnd: self aaScanMaskGet) = 0
  27849.             ifTrue:[self clearSpanBuffer].
  27850.         self clearSpanBufferPut: 0].
  27851.  
  27852.     hasFill _ self findNextExternalFillFromAET.
  27853.     engineStopped ifTrue:[^interpreterProxy primitiveFail].
  27854.     hasFill ifTrue:[self storeFillStateInto: fillOop].
  27855.     interpreterProxy failed ifFalse:[
  27856.         hasFill
  27857.             ifTrue:[    self statePut: GEStateWaitingForFill]
  27858.             ifFalse:[    self wbStackClear.
  27859.                     self spanEndAAPut: 0.
  27860.                     self statePut: GEStateBlitBuffer].
  27861.         self storeEngineStateInto: engine.
  27862.         interpreterProxy pop: 2.
  27863.         interpreterProxy pushBool: hasFill not.
  27864.         doProfileStats ifTrue:[
  27865.             self incrementStat: GWCountNextFillEntry by: 1.
  27866.             self incrementStat: GWTimeNextFillEntry by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  27867.     ].! !
  27868.  
  27869. !BalloonEngineBase methodsFor: 'primitives-incremental' stamp: 'ar 5/13/2000 15:00'!
  27870. primitiveNextGlobalEdgeEntry
  27871.     "Note: No need to load either bitBlt or spanBuffer"
  27872.     | edgeOop hasEdge edge |
  27873.     self export: true.
  27874.     self inline: false.
  27875.     doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  27876.     interpreterProxy methodArgumentCount = 1
  27877.         ifFalse:[^interpreterProxy primitiveFail].
  27878.     edgeOop _ interpreterProxy stackObjectValue: 0.
  27879.     engine _ interpreterProxy stackObjectValue: 1.
  27880.     interpreterProxy failed ifTrue:[^nil].
  27881.     (self quickLoadEngineFrom: engine requiredState: GEStateAddingFromGET)
  27882.         ifFalse:[^interpreterProxy primitiveFail].
  27883.  
  27884.     hasEdge _ self findNextExternalEntryFromGET.
  27885.     hasEdge ifTrue:[
  27886.         edge _ getBuffer at: self getStartGet.
  27887.         self storeEdgeStateFrom: edge into: edgeOop.
  27888.         self getStartPut: self getStartGet + 1].
  27889.  
  27890.     interpreterProxy failed ifTrue:[^nil].
  27891.  
  27892.     hasEdge
  27893.         ifTrue:[    self statePut: GEStateWaitingForEdge] "Wait for adding edges"
  27894.         ifFalse:[ "Start scanning the AET"
  27895.                 self statePut: GEStateScanningAET.
  27896.                 self clearSpanBufferPut: 1. "Clear span buffer at next entry"
  27897.                 self aetStartPut: 0.
  27898.                 self wbStackClear].
  27899.     self storeEngineStateInto: engine.
  27900.  
  27901.     interpreterProxy pop: 2.
  27902.     interpreterProxy pushBool: hasEdge not.
  27903.     doProfileStats ifTrue:[
  27904.         self incrementStat: GWCountNextGETEntry by: 1.
  27905.         self incrementStat: GWTimeNextGETEntry by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  27906. ! !
  27907.  
  27908. !BalloonEngineBase methodsFor: 'primitives-rendering' stamp: 'ar 5/12/2000 16:40'!
  27909. loadRenderingState
  27910.     "Load the entire state from the interpreter for the rendering primitives"
  27911.     | edgeOop fillOop state |
  27912.     self inline: false.
  27913.     interpreterProxy methodArgumentCount = 2
  27914.         ifFalse:[^interpreterProxy primitiveFail].
  27915.     fillOop _ interpreterProxy stackObjectValue: 0.
  27916.     edgeOop _ interpreterProxy stackObjectValue: 1.
  27917.     engine _ interpreterProxy stackObjectValue: 2.
  27918.     interpreterProxy failed ifTrue:[^false].
  27919.     (self quickLoadEngineFrom: engine)
  27920.         ifFalse:[^false].
  27921.  
  27922.     "Load span buffer and bitBlt"
  27923.     (self loadSpanBufferFrom:
  27924.         (interpreterProxy fetchPointer: BESpanIndex ofObject: engine))
  27925.             ifFalse:[^false].
  27926.     (self loadBitBltFrom: 
  27927.         (interpreterProxy fetchPointer: BEBitBltIndex ofObject: engine))
  27928.             ifFalse:[^false].
  27929.     (self loadFormsFrom:
  27930.         (interpreterProxy fetchPointer: BEFormsIndex ofObject: engine))
  27931.             ifFalse:[^false].
  27932.     "Check edgeOop and fillOop"
  27933.     (interpreterProxy slotSizeOf: edgeOop) < ETBalloonEdgeDataSize 
  27934.         ifTrue:[^false].
  27935.     (interpreterProxy slotSizeOf: fillOop) < FTBalloonFillDataSize 
  27936.         ifTrue:[^false].
  27937.  
  27938.     "Note: Rendering can only take place if we're not in one of the intermediate
  27939.     (e.g., external) states."
  27940.     state _ self stateGet.
  27941.     (state = GEStateWaitingForEdge or:[
  27942.         state = GEStateWaitingForFill or:[
  27943.             state = GEStateWaitingChange]]) ifTrue:[^false].
  27944.  
  27945.     ^true! !
  27946.  
  27947. !BalloonEngineBase methodsFor: 'primitives-rendering' stamp: 'ar 5/11/2000 23:08'!
  27948. primitiveRenderImage
  27949.     "Start/Proceed rendering the entire image"
  27950.     self export: true.
  27951.     self inline: false.
  27952.  
  27953.     self loadRenderingState ifFalse:[^interpreterProxy primitiveFail].
  27954.  
  27955.     self proceedRenderingScanline. "Finish this scan line"
  27956.     engineStopped ifTrue:[^self storeRenderingState].
  27957.     self proceedRenderingImage. "And go on as usual"
  27958.  
  27959.     self storeRenderingState.! !
  27960.  
  27961. !BalloonEngineBase methodsFor: 'primitives-rendering' stamp: 'ar 5/11/2000 23:07'!
  27962. primitiveRenderScanline
  27963.     "Start rendering the entire image"
  27964.     self export: true.
  27965.     self inline: false.
  27966.  
  27967.     self loadRenderingState ifFalse:[^interpreterProxy primitiveFail].
  27968.  
  27969.     self proceedRenderingScanline. "Finish the current scan line"
  27970.  
  27971.     self storeRenderingState.! !
  27972.  
  27973. !BalloonEngineBase methodsFor: 'primitives-rendering' stamp: 'ar 5/13/2000 15:00'!
  27974. proceedRenderingImage
  27975.     "This is the main rendering entry"
  27976.     | external |
  27977.     self inline: false.
  27978.     [self finishedProcessing] whileFalse:[
  27979.         doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  27980.         external _ self findNextExternalEntryFromGET.
  27981.         doProfileStats ifTrue:[
  27982.             self incrementStat: GWCountNextGETEntry by: 1.
  27983.             self incrementStat: GWTimeNextGETEntry by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  27984.         engineStopped ifTrue:[^self statePut: GEStateAddingFromGET].
  27985.         external ifTrue:[
  27986.             self statePut: GEStateWaitingForEdge.
  27987.             ^self stopBecauseOf: GErrorGETEntry.
  27988.         ]. 
  27989.         self aetStartPut: 0.
  27990.         self wbStackClear.
  27991.         self clearSpanBufferPut: 1.
  27992.  
  27993.         doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  27994.         (self clearSpanBufferGet ~= 0 and:[(self currentYGet bitAnd: self aaScanMaskGet) = 0])
  27995.             ifTrue:[self clearSpanBuffer].
  27996.         self clearSpanBufferPut: 0.
  27997.         external _ self findNextExternalFillFromAET.
  27998.         doProfileStats ifTrue:[
  27999.             self incrementStat: GWCountNextFillEntry by: 1.
  28000.             self incrementStat: GWTimeNextFillEntry by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  28001.         engineStopped ifTrue:[^self statePut: GEStateScanningAET].
  28002.         external ifTrue:[
  28003.             self statePut: GEStateWaitingForFill.
  28004.             ^self stopBecauseOf: GErrorFillEntry.
  28005.         ].
  28006.         self wbStackClear.
  28007.         self spanEndAAPut: 0.
  28008.  
  28009.         doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  28010.         (self currentYGet bitAnd: self aaScanMaskGet) = self aaScanMaskGet ifTrue:[
  28011.             self displaySpanBufferAt: self currentYGet.
  28012.             self postDisplayAction.
  28013.         ].
  28014.         doProfileStats ifTrue:[
  28015.             self incrementStat: GWCountDisplaySpan by: 1.
  28016.             self incrementStat: GWTimeDisplaySpan by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  28017.         engineStopped ifTrue:[^self statePut: GEStateBlitBuffer].
  28018.         self finishedProcessing ifTrue:[^0].
  28019.         self aetStartPut: 0.
  28020.         self currentYPut: self currentYGet + 1.
  28021.  
  28022.         doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  28023.         external _ self findNextExternalUpdateFromAET.
  28024.         doProfileStats ifTrue:[
  28025.             self incrementStat: GWCountNextAETEntry by: 1.
  28026.             self incrementStat: GWTimeNextAETEntry by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  28027.         engineStopped ifTrue:[^self statePut: GEStateUpdateEdges].
  28028.         external ifTrue:[
  28029.             self statePut: GEStateWaitingChange.
  28030.             ^self stopBecauseOf: GErrorAETEntry.
  28031.         ].
  28032.     ].! !
  28033.  
  28034. !BalloonEngineBase methodsFor: 'primitives-rendering' stamp: 'ar 5/13/2000 15:00'!
  28035. proceedRenderingScanline
  28036.     "Proceed rendering the current scan line.
  28037.     This method may be called after some Smalltalk code has been executed inbetween."
  28038.     "This is the main rendering entry"
  28039.     | external state |
  28040.     self inline: false.
  28041.     state _ self stateGet.
  28042.  
  28043.     state = GEStateUnlocked ifTrue:[
  28044.         self initializeGETProcessing.
  28045.         engineStopped ifTrue:[^0].
  28046.         state _ GEStateAddingFromGET.
  28047.     ]. 
  28048.  
  28049.     state = GEStateAddingFromGET ifTrue:[
  28050.         doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  28051.         external _ self findNextExternalEntryFromGET.
  28052.         doProfileStats ifTrue:[
  28053.             self incrementStat: GWCountNextGETEntry by: 1.
  28054.             self incrementStat: GWTimeNextGETEntry by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  28055.         engineStopped ifTrue:[^self statePut: GEStateAddingFromGET].
  28056.         external ifTrue:[
  28057.             self statePut: GEStateWaitingForEdge.
  28058.             ^self stopBecauseOf: GErrorGETEntry.
  28059.         ]. 
  28060.         self aetStartPut: 0.
  28061.         self wbStackClear.
  28062.         self clearSpanBufferPut: 1.
  28063.         state _ GEStateScanningAET.
  28064.     ].
  28065.  
  28066.     state = GEStateScanningAET ifTrue:[
  28067.         doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  28068.         (self clearSpanBufferGet ~= 0 and:[(self currentYGet bitAnd: self aaScanMaskGet) = 0])
  28069.             ifTrue:[self clearSpanBuffer].
  28070.         self clearSpanBufferPut: 0.
  28071.         external _ self findNextExternalFillFromAET.
  28072.         doProfileStats ifTrue:[
  28073.             self incrementStat: GWCountNextFillEntry by: 1.
  28074.             self incrementStat: GWTimeNextFillEntry by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  28075.         engineStopped ifTrue:[^self statePut: GEStateScanningAET].
  28076.         external ifTrue:[
  28077.             self statePut: GEStateWaitingForFill.
  28078.             ^self stopBecauseOf: GErrorFillEntry.
  28079.         ].
  28080.         state _ GEStateBlitBuffer.
  28081.         self wbStackClear.
  28082.         self spanEndAAPut: 0.
  28083.     ].
  28084.  
  28085.     state = GEStateBlitBuffer ifTrue:[
  28086.         doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  28087.         (self currentYGet bitAnd: self aaScanMaskGet) = self aaScanMaskGet ifTrue:[
  28088.             self displaySpanBufferAt: self currentYGet.
  28089.             self postDisplayAction.
  28090.         ].
  28091.         doProfileStats ifTrue:[
  28092.             self incrementStat: GWCountDisplaySpan by: 1.
  28093.             self incrementStat: GWTimeDisplaySpan by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  28094.         engineStopped ifTrue:[^self statePut: GEStateBlitBuffer].
  28095.         self finishedProcessing ifTrue:[^0].
  28096.         state _ GEStateUpdateEdges.
  28097.         self aetStartPut: 0.
  28098.         self currentYPut: self currentYGet + 1.
  28099.     ].
  28100.  
  28101.     state = GEStateUpdateEdges ifTrue:[
  28102.         doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  28103.         external _ self findNextExternalUpdateFromAET.
  28104.         doProfileStats ifTrue:[
  28105.             self incrementStat: GWCountNextAETEntry by: 1.
  28106.             self incrementStat: GWTimeNextAETEntry by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  28107.         engineStopped ifTrue:[^self statePut: GEStateUpdateEdges].
  28108.         external ifTrue:[
  28109.             self statePut: GEStateWaitingChange.
  28110.             ^self stopBecauseOf: GErrorAETEntry.
  28111.         ].
  28112.         self statePut: GEStateAddingFromGET.
  28113.     ].! !
  28114.  
  28115. !BalloonEngineBase methodsFor: 'primitives-rendering' stamp: 'ar 10/31/1998 23:54'!
  28116. storeRenderingState
  28117.     self inline: false.
  28118.     interpreterProxy failed ifTrue:[^nil].
  28119.     engineStopped ifTrue:[
  28120.         "Check the stop reason and store the required information"
  28121.         self storeStopStateIntoEdge: (interpreterProxy stackObjectValue: 1) 
  28122.             fill: (interpreterProxy stackObjectValue: 0).
  28123.     ].
  28124.     self storeEngineStateInto: engine.
  28125.     interpreterProxy pop: 3.
  28126.     interpreterProxy pushInteger: self stopReasonGet.! !
  28127.  
  28128. !BalloonEngineBase methodsFor: 'primitives-other' stamp: 'ar 5/11/2000 23:06'!
  28129. primitiveAbortProcessing
  28130.     self export: true.
  28131.     self inline: false.
  28132.     interpreterProxy methodArgumentCount = 0
  28133.         ifFalse:[^interpreterProxy primitiveFail].
  28134.     engine _ interpreterProxy stackObjectValue: 0.
  28135.     interpreterProxy failed ifTrue:[^nil].
  28136.     (self quickLoadEngineFrom: engine)
  28137.         ifFalse:[^interpreterProxy primitiveFail].
  28138.     self statePut: GEStateCompleted.
  28139.     self storeEngineStateInto: engine.! !
  28140.  
  28141. !BalloonEngineBase methodsFor: 'primitives-other' stamp: 'ar 5/11/2000 23:12'!
  28142. primitiveCopyBuffer
  28143.     | buf1 buf2 diff src dst |
  28144.     self export: true.
  28145.     self inline: false.
  28146.  
  28147.     self var: #src declareC:'int * src'.
  28148.     self var: #dst declareC:'int * dst'.
  28149.  
  28150.     interpreterProxy methodArgumentCount = 2
  28151.         ifFalse:[^interpreterProxy primitiveFail].
  28152.  
  28153.     buf2 _ interpreterProxy stackObjectValue: 0.
  28154.     buf1 _ interpreterProxy stackObjectValue: 1.
  28155.     interpreterProxy failed ifTrue:[^nil].
  28156.     "Make sure the old buffer is properly initialized"
  28157.     (self loadWorkBufferFrom: buf1) 
  28158.         ifFalse:[^interpreterProxy primitiveFail].
  28159.     "Make sure the buffers are of the same type"
  28160.     (interpreterProxy fetchClassOf: buf1) = (interpreterProxy fetchClassOf: buf2)
  28161.         ifFalse:[^interpreterProxy primitiveFail].
  28162.     "Make sure buf2 is at least of the size of buf1"
  28163.     diff _ (interpreterProxy slotSizeOf: buf2) - (interpreterProxy slotSizeOf: buf1).
  28164.     diff < 0 ifTrue:[^interpreterProxy primitiveFail].
  28165.  
  28166.     "Okay - ready for copying. First of all just copy the contents up to wbTop"
  28167.     src _ workBuffer.
  28168.     dst _ interpreterProxy firstIndexableField: buf2.
  28169.     0 to: self wbTopGet-1 do:[:i|
  28170.         dst at: i put: (src at: i).
  28171.     ].
  28172.     "Adjust wbSize and wbTop in the new buffer"
  28173.     dst at: GWBufferTop put: self wbTopGet + diff.
  28174.     dst at: GWSize put: self wbSizeGet + diff.
  28175.     "Now copy the entries from wbTop to wbSize"
  28176.     src _ src + self wbTopGet.
  28177.     dst _ dst + self wbTopGet + diff.
  28178.     0 to: (self wbSizeGet - self wbTopGet - 1) do:[:i|
  28179.         dst at: i put: (src at: i).
  28180.     ].
  28181.     "Okay, done. Check the new buffer by loading the state from it"
  28182.     (self loadWorkBufferFrom: buf2) 
  28183.         ifFalse:[^interpreterProxy primitiveFail].
  28184.     interpreterProxy pop: 2. "Leave rcvr on stack"
  28185. ! !
  28186.  
  28187. !BalloonEngineBase methodsFor: 'primitives-other' stamp: 'ar 5/11/2000 23:05'!
  28188. primitiveDoProfileStats
  28189.     "Turn on/off profiling. Return the old value of the flag."
  28190.     | oldValue newValue |
  28191.     self inline: false.
  28192.     self export: true.
  28193.     oldValue _ doProfileStats.
  28194.     newValue _ interpreterProxy stackObjectValue: 0.
  28195.     newValue _ interpreterProxy booleanValueOf: newValue.
  28196.     interpreterProxy failed ifFalse:[
  28197.         doProfileStats _ newValue.
  28198.         interpreterProxy pop: 2. "Pop rcvr, arg"
  28199.         interpreterProxy pushBool: oldValue.
  28200.     ].! !
  28201.  
  28202. !BalloonEngineBase methodsFor: 'primitives-other' stamp: 'ar 5/13/2000 14:59'!
  28203. primitiveFinishedProcessing
  28204.     | finished |
  28205.     self export: true.
  28206.     self inline: false.
  28207.     doProfileStats ifTrue:[geProfileTime _ interpreterProxy ioMicroMSecs].
  28208.     interpreterProxy methodArgumentCount = 0
  28209.         ifFalse:[^interpreterProxy primitiveFail].
  28210.     engine _ interpreterProxy stackObjectValue: 0.
  28211.     interpreterProxy failed ifTrue:[^nil].
  28212.     (self quickLoadEngineFrom: engine)
  28213.         ifFalse:[^interpreterProxy primitiveFail].
  28214.     finished _ self finishedProcessing.
  28215.     self storeEngineStateInto: engine.
  28216.     interpreterProxy pop: 1.
  28217.     interpreterProxy pushBool: finished.
  28218.     doProfileStats ifTrue:[
  28219.         self incrementStat: GWCountFinishTest by: 1.
  28220.         self incrementStat: GWTimeFinishTest by: (interpreterProxy ioMicroMSecs - geProfileTime)].
  28221. ! !
  28222.  
  28223. !BalloonEngineBase methodsFor: 'primitives-other' stamp: 'ar 5/11/2000 23:09'!
  28224. primitiveInitializeBuffer
  28225.     | wbOop size |
  28226.     self export: true.
  28227.     self inline: false.
  28228.     interpreterProxy methodArgumentCount = 1
  28229.         ifFalse:[^interpreterProxy primitiveFail].
  28230.     wbOop _ interpreterProxy stackObjectValue: 0.
  28231.     interpreterProxy failed ifTrue:[^nil].
  28232.     (interpreterProxy isWords: wbOop) 
  28233.         ifFalse:[^interpreterProxy primitiveFail].
  28234.     (size _ interpreterProxy slotSizeOf: wbOop) < GWMinimalSize
  28235.         ifTrue:[^interpreterProxy primitiveFail].
  28236.     workBuffer _ interpreterProxy firstIndexableField: wbOop.
  28237.     objBuffer _ workBuffer + GWHeaderSize.
  28238.     self magicNumberPut: GWMagicNumber.
  28239.     self wbSizePut: size.
  28240.     self wbTopPut: size.
  28241.     self statePut: GEStateUnlocked.
  28242.     self objStartPut: GWHeaderSize.
  28243.     self objUsedPut: 4.    "Dummy fill object"
  28244.     self objectTypeOf: 0 put: GEPrimitiveFill.
  28245.     self objectLengthOf: 0 put: 4.
  28246.     self objectIndexOf: 0 put: 0.
  28247.     self getStartPut: 0.
  28248.     self getUsedPut: 0.
  28249.     self aetStartPut: 0.
  28250.     self aetUsedPut: 0.
  28251.     self stopReasonPut: 0.
  28252.     self needsFlushPut: 0.
  28253.     self clipMinXPut: 0.
  28254.     self clipMaxXPut: 0.
  28255.     self clipMinYPut: 0.
  28256.     self clipMaxYPut: 0.
  28257.     self currentZPut: 0.
  28258.     self resetGraphicsEngineStats.
  28259.     self initEdgeTransform.
  28260.     self initColorTransform.
  28261.     interpreterProxy pop: 2.
  28262.     interpreterProxy push: wbOop.! !
  28263.  
  28264. !BalloonEngineBase methodsFor: 'primitives-other' stamp: 'ar 5/11/2000 23:08'!
  28265. primitiveRegisterExternalEdge
  28266.     | rightFillIndex leftFillIndex initialZ initialY initialX index  edge |
  28267.     self export: true.
  28268.     self inline: false.
  28269.     interpreterProxy methodArgumentCount = 6 
  28270.         ifFalse:[^interpreterProxy primitiveFail].
  28271.     rightFillIndex _ interpreterProxy positive32BitValueOf: (interpreterProxy stackValue: 0).
  28272.     leftFillIndex _ interpreterProxy positive32BitValueOf: (interpreterProxy stackValue: 1).
  28273.     initialZ _ interpreterProxy stackIntegerValue: 2.
  28274.     initialY _ interpreterProxy stackIntegerValue: 3.
  28275.     initialX _ interpreterProxy stackIntegerValue: 4.
  28276.     index _ interpreterProxy stackIntegerValue: 5.
  28277.     engine _ interpreterProxy stackObjectValue: 6.
  28278.     interpreterProxy failed ifTrue:[^nil].
  28279.     (self quickLoadEngineFrom: engine requiredState: GEStateUnlocked)
  28280.         ifFalse:[^interpreterProxy primitiveFail].
  28281.  
  28282.     (self allocateObjEntry: GEBaseEdgeSize) 
  28283.         ifFalse:[^interpreterProxy primitiveFail].
  28284.  
  28285.     "Make sure the fills are okay"
  28286.     (self isFillOkay: leftFillIndex)
  28287.         ifFalse:[^interpreterProxy primitiveFail].
  28288.     (self isFillOkay: rightFillIndex)
  28289.         ifFalse:[^interpreterProxy primitiveFail].
  28290.  
  28291.     edge _ objUsed.
  28292.     objUsed _ edge + GEBaseEdgeSize.
  28293.     "Install type and length"
  28294.     self objectTypeOf: edge put: GEPrimitiveEdge.
  28295.     self objectLengthOf: edge put: GEBaseEdgeSize.
  28296.     self objectIndexOf: edge put: index.
  28297.     "Install remaining stuff"
  28298.     self edgeXValueOf: edge put: initialX.
  28299.     self edgeYValueOf: edge put: initialY.
  28300.     self edgeZValueOf: edge put: initialZ.
  28301.     self edgeLeftFillOf: edge put: (self transformColor: leftFillIndex).
  28302.     self edgeRightFillOf: edge put: (self transformColor: rightFillIndex).
  28303.     engineStopped ifTrue:[^interpreterProxy primitiveFail].
  28304.  
  28305.     interpreterProxy failed ifFalse:[
  28306.         self storeEngineStateInto: engine.
  28307.         interpreterProxy pop: 6. "Leave rcvr on stack"
  28308.     ].! !
  28309.  
  28310. !BalloonEngineBase methodsFor: 'primitives-other' stamp: 'ar 5/11/2000 23:14'!
  28311. primitiveRegisterExternalFill
  28312.     | index  fill |
  28313.     self export: true.
  28314.     self inline: false.
  28315.     interpreterProxy methodArgumentCount = 1 
  28316.         ifFalse:[^interpreterProxy primitiveFail].
  28317.     index _ interpreterProxy stackIntegerValue: 0.
  28318.     engine _ interpreterProxy stackObjectValue: 1.
  28319.     interpreterProxy failed ifTrue:[^nil].
  28320.     (self quickLoadEngineFrom: engine requiredState: GEStateUnlocked)
  28321.         ifFalse:[^interpreterProxy primitiveFail].
  28322.  
  28323.     "Note: We *must* not allocate any fill with index 0"
  28324.     fill _ 0.
  28325.     [fill = 0] whileTrue:[
  28326.         (self allocateObjEntry: GEBaseEdgeSize) 
  28327.             ifFalse:[^interpreterProxy primitiveFail].
  28328.         fill _ objUsed.
  28329.         objUsed _ fill + GEBaseFillSize.
  28330.         "Install type and length"
  28331.         self objectTypeOf: fill put: GEPrimitiveFill.
  28332.         self objectLengthOf: fill put: GEBaseFillSize.
  28333.         self objectIndexOf: fill put: index.
  28334.     ].
  28335.  
  28336.     interpreterProxy failed ifFalse:[
  28337.         self storeEngineStateInto: engine.
  28338.         interpreterProxy pop: 2.
  28339.         interpreterProxy pushInteger: fill.
  28340.     ].! !
  28341.  
  28342. !BalloonEngineBase methodsFor: 'allocating' stamp: 'ar 10/29/1998 18:37'!
  28343. allocateAETEntry: nSlots
  28344.     "Allocate n slots in the active edge table"
  28345.     ^self needAvailableSpace: nSlots! !
  28346.  
  28347. !BalloonEngineBase methodsFor: 'allocating' stamp: 'ar 10/28/1998 21:06'!
  28348. allocateGETEntry: nSlots
  28349.     "Allocate n slots in the global edge table"
  28350.     | srcIndex dstIndex |
  28351.     self inline: false.
  28352.     "First allocate nSlots in the AET"
  28353.     (self allocateAETEntry: nSlots) ifFalse:[^false].
  28354.     self aetUsedGet = 0 ifFalse:["Then move the AET upwards"
  28355.         srcIndex _ self aetUsedGet.
  28356.         dstIndex _ self aetUsedGet + nSlots.
  28357.         1 to: self aetUsedGet do:[:i|
  28358.             aetBuffer at: (dstIndex _ dstIndex - 1) put: (aetBuffer at: (srcIndex _ srcIndex - 1))].
  28359.     ].
  28360.     aetBuffer _ aetBuffer + nSlots.
  28361.     ^true! !
  28362.  
  28363. !BalloonEngineBase methodsFor: 'allocating' stamp: 'ar 10/28/1998 21:16'!
  28364. allocateObjEntry: nSlots
  28365.     "Allocate n slots in the object buffer"
  28366.     | srcIndex dstIndex |
  28367.     self inline: false.
  28368.     "First allocate nSlots in the GET"
  28369.     (self allocateGETEntry: nSlots) ifFalse:[^false].
  28370.     self getUsedGet = 0 ifFalse:["Then move the GET upwards"
  28371.         srcIndex _ self getUsedGet.
  28372.         dstIndex _ self getUsedGet + nSlots.
  28373.         1 to: self getUsedGet do:[:i|
  28374.             getBuffer at: (dstIndex _ dstIndex - 1) put: (getBuffer at: (srcIndex _ srcIndex - 1))].
  28375.     ].
  28376.     getBuffer _ getBuffer + nSlots.
  28377.     ^true! !
  28378.  
  28379. !BalloonEngineBase methodsFor: 'allocating' stamp: 'ar 10/29/1998 18:37'!
  28380. allocateStackEntry: nSlots
  28381.     "AET and Stack allocation are symmetric"
  28382.     ^self needAvailableSpace: nSlots! !
  28383.  
  28384. !BalloonEngineBase methodsFor: 'allocating' stamp: 'ar 10/30/1998 19:24'!
  28385. allocateStackFillEntry
  28386.     ^self wbStackPush: self stackFillEntryLength! !
  28387.  
  28388. !BalloonEngineBase methodsFor: 'allocating' stamp: 'ar 10/30/1998 19:24'!
  28389. freeStackFillEntry
  28390.     self wbStackPop: self stackFillEntryLength.! !
  28391.  
  28392. !BalloonEngineBase methodsFor: 'allocating' stamp: 'ar 11/25/1998 02:19'!
  28393. needAvailableSpace: nSlots
  28394.     "Check if we have n slots available"
  28395.     GWHeaderSize + objUsed + self getUsedGet + self aetUsedGet + nSlots > self wbTopGet ifTrue:[
  28396.         self stopBecauseOf: GErrorNoMoreSpace.
  28397.         ^false
  28398.     ].
  28399.     ^true! !
  28400.  
  28401. !BalloonEngineBase methodsFor: 'GET processing' stamp: 'ar 11/1/1998 01:07'!
  28402. addEdgeToGET: edge
  28403.     self inline: false.
  28404.     (self allocateGETEntry: 1) ifFalse:[^0].
  28405.     "Install edge in the GET"
  28406.     getBuffer at: self getUsedGet put: edge.
  28407.     self getUsedPut: self getUsedGet + 1.! !
  28408.  
  28409. !BalloonEngineBase methodsFor: 'GET processing' stamp: 'ar 11/25/1998 00:41'!
  28410. createGlobalEdgeTable
  28411.     "Create the global edge table"
  28412.     | object end |
  28413.     self inline: false.
  28414.     object _ 0.
  28415.     end _ objUsed.
  28416.     [object < end] whileTrue:[
  28417.         "Note: addEdgeToGET: may fail on insufficient space but that's not a problem here"
  28418.         (self isEdge: object) ifTrue:[
  28419.             "Check if the edge starts below fillMaxY."
  28420.             (self edgeYValueOf: object) >= self fillMaxYGet ifFalse:[
  28421.                 self checkedAddEdgeToGET: object.
  28422.             ].
  28423.         ].
  28424.         object _ object + (self objectLengthOf: object).
  28425.     ].! !
  28426.  
  28427. !BalloonEngineBase methodsFor: 'GET processing' stamp: 'ar 11/9/1998 15:36'!
  28428. findNextExternalEntryFromGET
  28429.     "Check the global edge table for any entries that cannot be handled by the engine itself.
  28430.     If there are any, return true. Otherwise, initialize the the edge and add it to the AET"
  28431.     | yValue edge type |
  28432.     yValue _ self currentYGet.
  28433.     "As long as we have entries in the GET"
  28434.     [self getStartGet < self getUsedGet] whileTrue:[
  28435.         edge _ getBuffer at: self getStartGet.
  28436.         (self edgeYValueOf: edge) > yValue ifTrue:[^false]. "No more edges to add"
  28437.         type _ self objectTypeOf: edge.
  28438.         (type bitAnd: GEPrimitiveWideMask) = GEPrimitiveEdge 
  28439.             ifTrue:[^true]. "This is an external edge"
  28440.         "Note: We must make sure not to do anything with the edge if there is not
  28441.         enough room in the AET"
  28442.         (self needAvailableSpace: 1) ifFalse:[^false]. "No more room"
  28443.         "Process the edge in the engine itself"
  28444.         self dispatchOn: type in: EdgeInitTable.
  28445.         "Insert the edge into the AET"
  28446.         self insertEdgeIntoAET: edge.
  28447.         self getStartPut: self getStartGet + 1.
  28448.     ].
  28449.     "No entries in GET"
  28450.     ^false! !
  28451.  
  28452. !BalloonEngineBase methodsFor: 'GET processing' stamp: 'ar 10/28/1998 21:07'!
  28453. getSorts: edge1 before: edge2
  28454.     "Return true if the edge at index i should sort before the edge at index j."
  28455.     | diff |
  28456.     self inline: false.
  28457.     edge1 = edge2 ifTrue:[^true].
  28458.     "First, sort by Y"
  28459.     diff _ (self edgeYValueOf: edge1) - (self edgeYValueOf: edge2).
  28460.     diff = 0 ifFalse:[^diff < 0].
  28461.     "Then, by X"
  28462.     diff _ (self edgeXValueOf: edge1) - (self edgeXValueOf: edge2).
  28463.     ^diff < 0! !
  28464.  
  28465. !BalloonEngineBase methodsFor: 'GET processing' stamp: 'ar 11/25/1998 00:41'!
  28466. initializeGETProcessing
  28467.     "Initialization stuff that needs to be done before any processing can take place."
  28468.     self inline: false.
  28469.  
  28470.     "Make sure aaLevel is initialized"
  28471.     self setAALevel: self aaLevelGet.
  28472.  
  28473.     self clipMinXGet < 0 ifTrue:[self clipMinXPut: 0].
  28474.     self clipMaxXGet > self spanSizeGet ifTrue:[self clipMaxXPut: self spanSizeGet].
  28475.     "Convert clipRect to aaLevel"
  28476.     self fillMinXPut: self clipMinXGet << self aaShiftGet.
  28477.     self fillMinYPut: self clipMinYGet << self aaShiftGet.
  28478.     self fillMaxXPut: self clipMaxXGet << self aaShiftGet.
  28479.     self fillMaxYPut: self clipMaxYGet << self aaShiftGet.
  28480.  
  28481.     "Reset GET and AET"
  28482.     self getUsedPut: 0.
  28483.     self aetUsedPut: 0.
  28484.     getBuffer _ aetBuffer _ objBuffer + objUsed.
  28485.  
  28486.     "Create the global edge table"
  28487.     self createGlobalEdgeTable.
  28488.     engineStopped ifTrue:[^nil].
  28489.  
  28490.     self getUsedGet = 0 ifTrue:[
  28491.         "Nothing to do"
  28492.         self currentYPut: self fillMaxYGet.
  28493.         ^0].
  28494.  
  28495.     "Sort entries in the GET"
  28496.     self sortGlobalEdgeTable.
  28497.  
  28498.     "Find the first y value to be processed"
  28499.     self currentYPut: (self edgeYValueOf: (getBuffer at: 0)).
  28500.     self currentYGet < self fillMinYGet ifTrue:[self currentYPut: self fillMinYGet].
  28501.  
  28502.     "Load and clear the span buffer"
  28503.     self spanStartPut: 0.
  28504.     self spanEndPut: (self spanSizeGet << self aaShiftGet) - 1.
  28505.     self clearSpanBuffer. "@@: Is this really necessary?!!"! !
  28506.  
  28507. !BalloonEngineBase methodsFor: 'GET processing' stamp: 'ar 10/27/1998 17:55'!
  28508. quickSortGlobalEdgeTable: array from: i to: j 
  28509.     "Sort elements i through j of self to be nondescending according to
  28510.     sortBlock."
  28511.     "Note: The original loop has been heavily re-written for C translation"
  28512.     | di dij dj tt ij k l n tmp again before |
  28513.     self var: #array declareC:'int *array'.
  28514.     self inline: false.
  28515.     "The prefix d means the data at that index."
  28516.     (n _ j + 1  - i) <= 1 ifTrue: [^0].    "Nothing to sort." 
  28517.      "Sort di,dj."
  28518.     di _ array at: i.
  28519.     dj _ array at: j.
  28520.     before _ self getSorts: di before: dj. "i.e., should di precede dj?"
  28521.     before ifFalse:[
  28522.         tmp _ array at: i.
  28523.         array at: i put: (array at: j).
  28524.         array at: j put: tmp.
  28525.         tt _ di.    di _ dj.    dj _ tt].
  28526.     n <= 2 ifTrue:[^0].
  28527.  
  28528.     "More than two elements."
  28529.     ij _ (i + j) // 2.  "ij is the midpoint of i and j."
  28530.     dij _ array at: ij.  "Sort di,dij,dj.  Make dij be their median."
  28531.     before _ (self getSorts: di before: dij). "i.e. should di precede dij?"
  28532.     before ifTrue:[
  28533.         before _ (self getSorts: dij before: dj). "i.e., should dij precede dj?"
  28534.         before ifFalse:["i.e., should dij precede dj?"
  28535.             tmp _ array at: j.
  28536.             array at: j put: (array at: ij).
  28537.             array at: ij put: tmp.
  28538.             dij _ dj]
  28539.     ] ifFalse:[  "i.e. di should come after dij"
  28540.         tmp _ array at: i.
  28541.         array at: i put: (array at: ij).
  28542.         array at: ij put: tmp.
  28543.          dij _ di].
  28544.     n <= 3 ifTrue:[^0].
  28545.  
  28546.      "More than three elements."
  28547.     "Find k>i and l<j such that dk,dij,dl are in reverse order.
  28548.     Swap k and l.  Repeat this procedure until k and l pass each other."
  28549.     k _ i.
  28550.     l _ j.
  28551.  
  28552.     again _ true.
  28553.     [again] whileTrue:[
  28554.         before _ true.
  28555.         [before] whileTrue:[
  28556.             k <= (l _ l - 1)
  28557.                 ifTrue:[    tmp _ array at: l.
  28558.                         before _ self getSorts: dij before: tmp]
  28559.                 ifFalse:[before _ false].
  28560.         ].
  28561.         before _ true.
  28562.         [before] whileTrue:[
  28563.             (k _ k + 1) <= l
  28564.                 ifTrue:[    tmp _ array at: k.
  28565.                         before _ self getSorts: tmp before: dij]
  28566.                 ifFalse:[before _ false]].
  28567.  
  28568.         again _ k <= l.
  28569.         again ifTrue:[
  28570.             tmp _ array at: k.
  28571.             array at: k put: (array at: l).
  28572.             array at: l put: tmp]].
  28573.  
  28574.     "Now l<k (either 1 or 2 less), and di through dl are all less than or equal to dk
  28575.     through dj.  Sort those two segments."
  28576.     self quickSortGlobalEdgeTable: array from: i to: l.
  28577.     self quickSortGlobalEdgeTable: array from: k to: j.! !
  28578.  
  28579. !BalloonEngineBase methodsFor: 'GET processing' stamp: 'ar 10/27/1998 23:34'!
  28580. sortGlobalEdgeTable
  28581.     "Sort the entire global edge table"
  28582.     self quickSortGlobalEdgeTable: getBuffer from: 0 to: self getUsedGet-1.! !
  28583.  
  28584. !BalloonEngineBase methodsFor: 'AET processing' stamp: 'ar 11/24/1998 22:47'!
  28585. findNextAETEdgeFrom: leftEdge
  28586.     | depth rightEdge |
  28587.     depth _ self edgeZValueOf: leftEdge.
  28588.     [self aetStartGet < self aetUsedGet] whileTrue:[
  28589.         rightEdge _ aetBuffer at: self aetStartGet.
  28590.         (self edgeZValueOf: rightEdge) >= depth ifTrue:[^rightEdge].
  28591.         self aetStartPut: self aetStartGet + 1.
  28592.     ].
  28593.     ^nil! !
  28594.  
  28595. !BalloonEngineBase methodsFor: 'AET processing' stamp: 'ar 11/25/1998 23:21'!
  28596. findNextExternalFillFromAET
  28597.     "Scan the active edge table. If there is any fill that cannot be handled by the engine itself,  return true. Otherwise handle the fills and return false."
  28598.     | leftEdge rightEdge leftX rightX |
  28599. "self currentYGet >= 680 ifTrue:[
  28600. self printAET.
  28601. self halt.
  28602. ]."
  28603.  
  28604.     self inline: false.
  28605.     leftX _ rightX _ self fillMaxXGet.
  28606.     [self aetStartGet < self aetUsedGet] whileTrue:[
  28607.         leftEdge _ rightEdge _ aetBuffer at: self aetStartGet.
  28608.         "TODO: We should check if leftX from last operation 
  28609.             is  greater than leftX from next edge.
  28610.             Currently, we rely here on spanEndAA
  28611.             from the span buffer fill."
  28612.         leftX _ rightX _ self edgeXValueOf: leftEdge.
  28613.         leftX >= self fillMaxXGet ifTrue:[^false]. "Nothing more visible"
  28614.         self quickRemoveInvalidFillsAt: leftX.
  28615.         "Check if we need to draw the edge"
  28616.         (self isWide: leftEdge) ifTrue:[
  28617.             self toggleWideFillOf: leftEdge.
  28618.             "leftX _ rightX _ self drawWideEdge: leftEdge from: leftX."
  28619.         ].
  28620.         (self areEdgeFillsValid: leftEdge) ifTrue:[
  28621.             self toggleFillsOf: leftEdge. "Adjust the fills"
  28622.             engineStopped ifTrue:[^false].
  28623.         ].
  28624.         self aetStartPut: self aetStartGet + 1.
  28625.         self aetStartGet < self aetUsedGet ifTrue:[
  28626.             rightEdge _ aetBuffer at: self aetStartGet.
  28627.             rightX _ self edgeXValueOf: rightEdge.
  28628.             rightX >= self fillMinXGet ifTrue:["This is the visible portion"
  28629.                 self fillAllFrom: leftX to: rightX.
  28630.                 "Fetch the currently active fill"
  28631.                 "fill _ self makeUnsignedFrom: self topFill.
  28632.                 fill = 0 ifFalse:[self fillSpan: fill from: leftX to: rightX max: self topRightX]"
  28633.             ].
  28634.         ].
  28635.     ].
  28636.     "Note: Due to pre-clipping we may have to draw remaining stuff with the last fill"
  28637.     rightX < self fillMaxXGet ifTrue:[
  28638.         self fillAllFrom: rightX to: self fillMaxXGet.
  28639.         "fill _ self makeUnsignedFrom: self topFill.
  28640.         fill = 0 ifFalse:[self fillSpan: fill from: rightX to: self fillMaxXGet max: self topRightX]."
  28641.     ].
  28642.     ^false! !
  28643.  
  28644. !BalloonEngineBase methodsFor: 'AET processing' stamp: 'ar 11/9/1998 15:36'!
  28645. findNextExternalUpdateFromAET
  28646.     "Check the active edge table for any entries that cannot be handled by the engine itself.
  28647.     If there are any, return true. Otherwise, step the the edge to the next y value."
  28648.     | edge count type |
  28649.     self inline: false.
  28650.     [self aetStartGet < self aetUsedGet] whileTrue:[
  28651.         edge _ aetBuffer at: self aetStartGet.
  28652.         count _ (self edgeNumLinesOf: edge) - 1.
  28653.         count = 0 ifTrue:[
  28654.             "Edge at end -- remove it"
  28655.             self removeFirstAETEntry
  28656.         ] ifFalse:[
  28657.             "Store remaining lines back"
  28658.             self edgeNumLinesOf: edge put: count.
  28659.             type _ self objectTypeOf: edge.
  28660.             (type bitAnd: GEPrimitiveWideMask) = GEPrimitiveEdge 
  28661.                 ifTrue:[^true]. "This is an external edge"
  28662.             self dispatchOn: type in: EdgeStepTable.
  28663.             self resortFirstAETEntry.
  28664.             self aetStartPut: self aetStartGet+1.
  28665.         ].
  28666.     ].
  28667.     ^false! !
  28668.  
  28669. !BalloonEngineBase methodsFor: 'AET processing' stamp: 'ar 10/28/1998 21:07'!
  28670. indexForInsertingIntoAET: edge
  28671.     "Find insertion point for the given edge in the AET"
  28672.     | initialX index |
  28673.     self inline: false.
  28674.     initialX _ self edgeXValueOf: edge.
  28675.     index _ 0.
  28676.     [index < self aetUsedGet and:[
  28677.         (self edgeXValueOf: (aetBuffer at: index)) < initialX]]
  28678.             whileTrue:[index _ index + 1].
  28679.     [index < self aetUsedGet and:[
  28680.         (self edgeXValueOf: (aetBuffer at: index)) = initialX and:[
  28681.             (self getSorts: (aetBuffer at: index) before: edge)]]]
  28682.                 whileTrue:[index _ index + 1].
  28683.     ^index! !
  28684.  
  28685. !BalloonEngineBase methodsFor: 'AET processing' stamp: 'ar 10/28/1998 19:52'!
  28686. insertEdgeIntoAET: edge
  28687.     "Insert the edge with the given index from the global edge table into the active edge table.
  28688.     The edge has already been stepped to the initial yValue -- thus remainingLines and rasterX
  28689.     are both set."
  28690.     | index |
  28691.     self inline: false.
  28692.  
  28693.     "Check for the number of lines remaining"
  28694.     (self edgeNumLinesOf: edge) <= 0 ifTrue:[^nil]. "Nothing to do"
  28695.  
  28696.     "Find insertion point"
  28697.     index _ self indexForInsertingIntoAET: edge.
  28698.  
  28699.     "And insert edge"
  28700.     self insertToAET: edge beforeIndex: index.! !
  28701.  
  28702. !BalloonEngineBase methodsFor: 'AET processing' stamp: 'ar 10/28/1998 21:07'!
  28703. insertToAET: edge beforeIndex: index
  28704.     "Insert the given edge into the AET."
  28705.     | i |
  28706.     self inline: false.
  28707.     "Make sure we have space in the AET"
  28708.     (self allocateAETEntry: 1) ifFalse:[^nil]. "Insufficient space in AET"
  28709.  
  28710.     i _ self aetUsedGet-1.
  28711.     [i < index] whileFalse:[
  28712.         aetBuffer at: i+1 put: (aetBuffer at: i).
  28713.         i _ i - 1.
  28714.     ].
  28715.     aetBuffer at: index put: edge.
  28716.     self aetUsedPut: self aetUsedGet + 1.! !
  28717.  
  28718. !BalloonEngineBase methodsFor: 'AET processing' stamp: 'ar 10/28/1998 01:39'!
  28719. moveAETEntryFrom: index edge: edge x: xValue
  28720.     "The entry at index is not in the right position of the AET. 
  28721.     Move it to the left until the position is okay."
  28722.     | newIndex |
  28723.     self inline: false.
  28724.     newIndex _ index.
  28725.     [newIndex > 0 and:[(self edgeXValueOf: (aetBuffer at: newIndex-1)) > xValue]]
  28726.         whileTrue:[    aetBuffer at: newIndex put: (aetBuffer at: newIndex-1).
  28727.                     newIndex _ newIndex - 1].
  28728.     aetBuffer at: newIndex put: edge.! !
  28729.  
  28730. !BalloonEngineBase methodsFor: 'AET processing' stamp: 'ar 10/28/1998 21:07'!
  28731. removeFirstAETEntry
  28732.     | index |
  28733.     self inline: false.
  28734.     index _ self aetStartGet.
  28735.     self aetUsedPut: self aetUsedGet - 1.
  28736.     [index < self aetUsedGet] whileTrue:[
  28737.         aetBuffer at: index put: (aetBuffer at: index + 1).
  28738.         index _ index + 1.
  28739.     ].! !
  28740.  
  28741. !BalloonEngineBase methodsFor: 'AET processing' stamp: 'ar 10/28/1998 21:07'!
  28742. resortFirstAETEntry
  28743.     | edge xValue leftEdge |
  28744.     self inline: false.
  28745.     self aetStartGet = 0 ifTrue:[^nil]. "Nothing to resort"
  28746.     edge _ aetBuffer at: self aetStartGet.
  28747.     xValue _ self edgeXValueOf: edge.
  28748.     leftEdge _ aetBuffer at: (self aetStartGet - 1).
  28749.     (self edgeXValueOf: leftEdge) <= xValue ifTrue:[^nil]. "Okay"
  28750.     self moveAETEntryFrom: self aetStartGet edge: edge x: xValue.! !
  28751.  
  28752. !BalloonEngineBase methodsFor: 'FILL processing' stamp: 'ar 11/24/1998 22:42'!
  28753. fillSorts: fillEntry1 before: fillEntry2
  28754.     "Return true if fillEntry1 should be drawn before fillEntry2"
  28755.     | diff |
  28756.     self inline: false.
  28757.     "First check the depth value"
  28758.     diff _ (self stackFillDepth: fillEntry1) - (self stackFillDepth: fillEntry2).
  28759.     diff = 0 ifFalse:[^diff > 0].
  28760.     "See the class comment for aetScanningProblems"
  28761.     ^(self cCoerce: (self makeUnsignedFrom: (self stackFillValue: fillEntry1)) to:'unsigned') <
  28762.         (self cCoerce: (self makeUnsignedFrom: (self stackFillValue: fillEntry2)) to: 'unsigned')! !
  28763.  
  28764. !BalloonEngineBase methodsFor: 'FILL processing' stamp: 'ar 11/25/1998 15:47'!
  28765. findStackFill: fillIndex depth: depth
  28766.     | index |
  28767.     index _ 0.
  28768.     [index < self stackFillSize and:[
  28769.         (self stackFillValue: index) ~= fillIndex or:[
  28770.             (self stackFillDepth: index) ~= depth]]]
  28771.                 whileTrue:[index _ index + self stackFillEntryLength].
  28772.     index >= self stackFillSize 
  28773.         ifTrue:[^-1]
  28774.         ifFalse:[^index].
  28775. ! !
  28776.  
  28777. !BalloonEngineBase methodsFor: 'FILL processing' stamp: 'ar 11/25/1998 15:48'!
  28778. hideFill: fillIndex depth: depth
  28779.     "Make the fill style with the given index invisible"
  28780.     | index newTopIndex newTop newDepth newRightX |
  28781.     self inline: false.
  28782.     index _ self findStackFill: fillIndex depth: depth.
  28783.     index = -1 ifTrue:[^false].
  28784.  
  28785.     index = 0 ifTrue:[
  28786.         self freeStackFillEntry.
  28787.         ^true].
  28788.  
  28789.     "Fill is visible - replace it with the last entry on the stack"
  28790.     self stackFillValue: index put: (self stackFillValue: 0).
  28791.     self stackFillDepth: index put: (self stackFillDepth: 0).
  28792.     self stackFillRightX: index put: (self stackFillRightX: 0).
  28793.     self freeStackFillEntry.
  28794.     (self stackFillSize <= self stackFillEntryLength) ifTrue:[^true]. "Done"
  28795.  
  28796.     "Find the new top fill"
  28797.     newTopIndex _ 0.
  28798.     index _ self stackFillEntryLength.
  28799.     [index < self stackFillSize] whileTrue:[
  28800.         (self fillSorts: index before: newTopIndex)
  28801.             ifTrue:[newTopIndex _ index].
  28802.         index _ index + self stackFillEntryLength.
  28803.     ].
  28804.     (newTopIndex + self stackFillEntryLength = self stackFillSize) 
  28805.         ifTrue:[^true]. "Top fill not changed"
  28806.     newTop _ self stackFillValue: newTopIndex.
  28807.     self stackFillValue: newTopIndex put: self topFillValue.
  28808.     self topFillValuePut: newTop.
  28809.     newDepth _ self stackFillDepth: newTopIndex.
  28810.     self stackFillDepth: newTopIndex put: self topFillDepth.
  28811.     self topFillDepthPut: newDepth.
  28812.     newRightX _ self stackFillRightX: newTopIndex.
  28813.     self stackFillRightX: newTopIndex put: self topFillRightX.
  28814.     self topFillRightXPut: newRightX.
  28815.     ^true! !
  28816.  
  28817. !BalloonEngineBase methodsFor: 'FILL processing' stamp: 'ar 11/25/1998 15:16'!
  28818. quickRemoveInvalidFillsAt: leftX
  28819.     "Remove any top fills if they have become invalid."
  28820.     self stackFillSize = 0 ifTrue:[^nil].
  28821.     [self topRightX <= leftX] whileTrue:[
  28822.         self hideFill: self topFill depth: self topDepth.
  28823.         self stackFillSize = 0 ifTrue:[^nil].
  28824.     ].! !
  28825.  
  28826. !BalloonEngineBase methodsFor: 'FILL processing' stamp: 'ar 11/25/1998 14:38'!
  28827. showFill: fillIndex depth: depth rightX: rightX
  28828.     self inline: false.
  28829.     (self allocateStackFillEntry) ifFalse:[^nil]. "Insufficient space"
  28830.     self stackFillValue: 0 put: fillIndex.
  28831.     self stackFillDepth: 0 put: depth.
  28832.     self stackFillRightX: 0 put: rightX.
  28833.     self stackFillSize = self stackFillEntryLength ifTrue:[^nil]. "No need to update"
  28834.  
  28835.     (self fillSorts: 0 before: self stackFillSize - self stackFillEntryLength) ifTrue:[
  28836.         "New top fill"
  28837.         self stackFillValue: 0 put: self topFillValue.
  28838.         self stackFillDepth: 0 put: self topFillDepth.
  28839.         self stackFillRightX: 0 put: self topFillRightX.
  28840.         self topFillValuePut: fillIndex.
  28841.         self topFillDepthPut: depth.
  28842.         self topFillRightXPut: rightX.
  28843.     ].! !
  28844.  
  28845. !BalloonEngineBase methodsFor: 'FILL processing' stamp: 'ar 11/25/1998 14:38'!
  28846. toggleFill: fillIndex depth: depth rightX: rightX
  28847.     "Make the fill style with the given index either visible or invisible"
  28848.     | hidden |
  28849.     self inline: false.
  28850.  
  28851.     self stackFillSize = 0 ifTrue:[
  28852.         (self allocateStackFillEntry) ifTrue:[
  28853.             self topFillValuePut: fillIndex.
  28854.             self topFillDepthPut: depth.
  28855.             self topFillRightXPut: rightX.
  28856.         ].
  28857.     ] ifFalse:[
  28858.         hidden _ self hideFill: fillIndex depth: depth.
  28859.         hidden ifFalse:[self showFill: fillIndex depth: depth rightX: rightX].
  28860.     ].! !
  28861.  
  28862. !BalloonEngineBase methodsFor: 'FILL processing' stamp: 'ar 11/25/1998 15:19'!
  28863. toggleFillsOf: edge
  28864.     | depth fillIndex |
  28865.     self inline: false.
  28866.  
  28867.     (self needAvailableSpace: self stackFillEntryLength * 2) 
  28868.         ifFalse:[^nil]. "Make sure we have enough space left"
  28869.     depth _ (self edgeZValueOf: edge) << 1.
  28870.     fillIndex _ self edgeLeftFillOf: edge.
  28871.     fillIndex = 0 ifFalse:[self toggleFill: fillIndex depth: depth rightX: 999999999].
  28872.     fillIndex _ self edgeRightFillOf: edge.
  28873.     fillIndex = 0 ifFalse:[self toggleFill: fillIndex depth: depth rightX: 999999999].
  28874.     self quickRemoveInvalidFillsAt: (self edgeXValueOf: edge).! !
  28875.  
  28876. !BalloonEngineBase methodsFor: 'FILL processing' stamp: 'ar 11/25/1998 15:50'!
  28877. toggleWideFillOf: edge
  28878.     | fill type lineWidth depth rightX index |
  28879.     self inline: false.
  28880.     type _ self edgeTypeOf: edge.
  28881.     dispatchedValue _ edge.
  28882.     self dispatchOn: type in: WideLineWidthTable.
  28883.     lineWidth _ dispatchReturnValue.
  28884.     self dispatchOn: type in: WideLineFillTable.
  28885.     fill _ dispatchReturnValue.
  28886.     fill = 0 ifTrue:[^nil].
  28887.     (self needAvailableSpace: self stackFillEntryLength) 
  28888.         ifFalse:[^nil]. "Make sure we have enough space left"
  28889.     depth _ (self edgeZValueOf: edge) << 1 + 1. "So lines sort before interior fills"
  28890.     rightX _ (self edgeXValueOf: edge) + lineWidth.
  28891.     index _ self findStackFill: fill depth: depth.
  28892.     index = -1 ifTrue:[
  28893.         self showFill: fill 
  28894.             depth: depth
  28895.             rightX: rightX.
  28896.     ] ifFalse:[
  28897.         (self stackFillRightX: index) < rightX
  28898.             ifTrue:[self stackFillRightX: index put: rightX].
  28899.     ].
  28900.     self quickRemoveInvalidFillsAt: (self edgeXValueOf: edge).! !
  28901.  
  28902. !BalloonEngineBase methodsFor: 'displaying' stamp: 'ar 11/9/1998 00:53'!
  28903. aaFirstPixelFrom: leftX to: rightX
  28904.     "Common function to compute the first full pixel for AA drawing"
  28905.     | firstPixel |
  28906.     self inline: true.
  28907.     firstPixel _ (leftX + self aaLevelGet - 1) bitAnd: (self aaLevelGet - 1) bitInvert32.
  28908.     firstPixel > rightX 
  28909.         ifTrue:[^rightX]
  28910.         ifFalse:[^firstPixel]! !
  28911.  
  28912. !BalloonEngineBase methodsFor: 'displaying' stamp: 'ar 11/9/1998 00:53'!
  28913. aaLastPixelFrom: leftX to: rightX
  28914.     "Common function to compute the last full pixel for AA drawing"
  28915.     self inline: true.
  28916.     ^(rightX - 1) bitAnd: (self aaLevelGet - 1) bitInvert32.! !
  28917.  
  28918. !BalloonEngineBase methodsFor: 'displaying' stamp: 'ar 11/9/1998 00:50'!
  28919. adjustAALevel
  28920.  
  28921.         "NOTE:     This method is (hopefully) obsolete due to unrolling 
  28922.                 the fill loops to deal with full pixels."
  28923.  
  28924.     "Adjust the span buffers values by the appropriate color offset for anti-aliasing.
  28925.     We do this by replicating the top bits of each color in the lower bits. The idea is that we can scale each color value uniquely from 0 to 255 and thus fill the entire range of colors."
  28926.     | adjustShift adjustMask x0 x1 pixelValue |
  28927.     self inline: false.
  28928.     adjustShift _ 8 - self aaColorShiftGet.
  28929.     adjustMask _ self aaColorMaskGet bitInvert32.
  28930.     x0 _ self spanStartGet >> self aaShiftGet.
  28931.     x1 _ self spanEndGet >> self aaShiftGet.
  28932.     [x0 < x1] whileTrue:[
  28933.         pixelValue _ spanBuffer at: x0.
  28934.         spanBuffer at: x0 put: (pixelValue bitOr: (pixelValue >> adjustShift bitAnd: adjustMask)).
  28935.         x0 _ x0 + 1].! !
  28936.  
  28937. !BalloonEngineBase methodsFor: 'displaying' stamp: 'ar 11/14/1998 19:31'!
  28938. clearSpanBuffer
  28939.     "Clear the current span buffer.
  28940.     The span buffer is only cleared in the area that has been used by the previous scan line."
  28941.     | x0 x1 |
  28942.     self inline: false.
  28943.     x0 _ self spanStartGet >> self aaShiftGet.
  28944.     x1 _ self spanEndGet >> self aaShiftGet + 1.
  28945.     x0 < 0 ifTrue:[x0 _ 0].
  28946.     x1 > self spanSizeGet ifTrue:[x1 _ self spanSizeGet].
  28947.     [x0 < x1] whileTrue:[
  28948.         spanBuffer at: x0 put: 0.
  28949.         x0 _ x0 + 1].
  28950.     self spanStartPut: self spanSizeGet.
  28951.     self spanEndPut: 0.! !
  28952.  
  28953. !BalloonEngineBase methodsFor: 'displaying' stamp: 'ar 5/12/2000 16:42'!
  28954. displaySpanBufferAt: y
  28955.     "Display the span buffer at the current scan line."
  28956.     | targetX0 targetX1 targetY |
  28957.     self inline: false.
  28958.     "self aaLevelGet > 1 ifTrue:[self adjustAALevel]."
  28959.     targetX0 _ self spanStartGet >> self aaShiftGet.
  28960.     targetX0 < self clipMinXGet ifTrue:[targetX0 _ self clipMinXGet].
  28961.     targetX1 _ (self spanEndGet + self aaLevelGet - 1) >> self aaShiftGet.
  28962.     targetX1 > self clipMaxXGet ifTrue:[targetX1 _ self clipMaxXGet].
  28963.     targetY _ y >> self aaShiftGet.
  28964.     (targetY < self clipMinYGet or:[targetY >= self clipMaxYGet or:[
  28965.         targetX1 < self clipMinXGet or:[targetX0 >= self clipMaxXGet]]]) ifTrue:[^0].
  28966.     self copyBitsFrom: targetX0 to: targetX1 at: targetY.! !
  28967.  
  28968. !BalloonEngineBase methodsFor: 'displaying' stamp: 'ar 11/25/1998 02:34'!
  28969. drawWideEdge: edge from: leftX
  28970.     "Draw the given edge starting from leftX with the edge's fill.
  28971.     Return the end value of the drawing operation."
  28972.     | rightX fill type lineWidth |
  28973.     self inline: false. "Not for the moment"
  28974.     type _ self edgeTypeOf: edge.
  28975.     dispatchedValue _ edge.
  28976.     self dispatchOn: type in: WideLineWidthTable.
  28977.     lineWidth _ dispatchReturnValue.
  28978.     self dispatchOn: type in: WideLineFillTable.
  28979.     fill _ self makeUnsignedFrom: dispatchReturnValue.
  28980.     fill = 0 ifTrue:[^leftX].
  28981.     "Check if this line is only partially visible"
  28982.     "self assert:(self isFillColor: fill)."
  28983.     rightX _ leftX + lineWidth.
  28984.     self fillSpan: fill from: leftX to: rightX.
  28985.     ^rightX! !
  28986.  
  28987. !BalloonEngineBase methodsFor: 'displaying' stamp: 'ar 11/25/1998 15:12'!
  28988. fillAllFrom: leftX to: rightX
  28989.     "Fill the span buffer from leftX to rightX with the given fill."
  28990.     | fill startX stopX |
  28991.     self inline: true.
  28992.     fill _ self topFill.
  28993.     startX _ leftX.
  28994.     stopX _ self topRightX.
  28995.     [stopX < rightX] whileTrue:[
  28996.         fill _ self makeUnsignedFrom: self topFill.
  28997.         fill = 0 ifFalse:[
  28998.             (self fillSpan: fill from: startX to: stopX) ifTrue:[^true]].
  28999.         self quickRemoveInvalidFillsAt: stopX.
  29000.         startX _ stopX.
  29001.         stopX _ self topRightX].
  29002.     fill _ self makeUnsignedFrom: self topFill.
  29003.     fill = 0 ifFalse:[^self fillSpan: fill from: startX to: rightX].
  29004.     ^false! !
  29005.  
  29006. !BalloonEngineBase methodsFor: 'displaying' stamp: 'ar 11/9/1998 16:10'!
  29007. fillBitmapSpan: bits from: leftX to: rightX
  29008.     "Fill the span buffer between leftEdge and rightEdge using the given bits.
  29009.     Note: We always start from zero - this avoids using huge bitmap buffers if the bitmap is to be displayed at the very far right hand side and also gives us a chance of using certain bitmaps (e.g., those with depth 32) directly."
  29010.     | x0 x1 x bitX colorMask colorShift baseShift fillValue |
  29011.     self inline: false.
  29012.     self var: #bits declareC:'int *bits'.
  29013.  
  29014.     x0 _ leftX.
  29015.     x1 _ rightX.
  29016.     bitX _ -1. "Hack for pre-increment"
  29017.     self aaLevelGet = 1 ifTrue:["Speedy version for no anti-aliasing"
  29018.         [x0 < x1] whileTrue:[
  29019.             fillValue _ (self cCoerce: bits to: 'int *') at: (bitX _ bitX + 1).
  29020.             spanBuffer at: x0 put: fillValue.
  29021.             x0 _ x0 + 1.
  29022.         ].
  29023.     ] ifFalse:["Generic version with anti-aliasing"
  29024.         colorMask _ self aaColorMaskGet.
  29025.         colorShift _ self aaColorShiftGet.
  29026.         baseShift _ self aaShiftGet.
  29027.         [x0 < x1] whileTrue:[
  29028.             x _ x0 >> baseShift.
  29029.             fillValue _ (self cCoerce: bits to: 'int *') at: (bitX _ bitX + 1).
  29030.             fillValue _ (fillValue bitAnd: colorMask) >> colorShift.
  29031.             spanBuffer at: x put: (spanBuffer at: x) + fillValue.
  29032.             x0 _ x0 + 1.
  29033.         ].
  29034.     ].
  29035.     x1 > self spanEndGet ifTrue:[self spanEndPut: x1].
  29036.     x1 > self spanEndAAGet ifTrue:[self spanEndAAPut: x1].! !
  29037.  
  29038. !BalloonEngineBase methodsFor: 'displaying' stamp: 'ar 11/8/1998 03:30'!
  29039. fillColorSpan: pixelValue32 from: leftX to: rightX
  29040.     "Fill the span buffer between leftEdge and rightEdge with the given pixel value."
  29041.     | x0 x1 |
  29042.     self inline: true.
  29043.     "Use a unrolled version for anti-aliased fills..."
  29044.     self aaLevelGet = 1
  29045.         ifFalse:[^self fillColorSpanAA: pixelValue32 x0: leftX x1: rightX].
  29046.     x0 _ leftX.
  29047.     x1 _ rightX.
  29048.     "Unroll the inner loop four times, since we're only storing data."
  29049.     [x0 + 4 < x1] whileTrue:[
  29050.         spanBuffer at: x0 put: pixelValue32.
  29051.         spanBuffer at: x0+1 put: pixelValue32.
  29052.         spanBuffer at: x0+2 put: pixelValue32.
  29053.         spanBuffer at: x0+3 put: pixelValue32.
  29054.         x0 _ x0+4.
  29055.     ].
  29056.     [x0 < x1] whileTrue:[
  29057.         spanBuffer at: x0 put: pixelValue32.
  29058.         x0 _ x0 + 1.
  29059.     ].! !
  29060.  
  29061. !BalloonEngineBase methodsFor: 'displaying' stamp: 'ar 11/9/1998 00:52'!
  29062. fillColorSpanAA: pixelValue32 x0: leftX x1: rightX
  29063.     "This is the inner loop for solid color fills with anti-aliasing.
  29064.     This loop has been unrolled for speed and quality into three parts:
  29065.         a) copy all pixels that fall into the first full pixel.
  29066.         b) copy aaLevel pixels between the first and the last full pixel
  29067.         c) copy all pixels that fall in the last full pixel"
  29068.     | colorMask baseShift x idx firstPixel lastPixel aaLevel pv32 |
  29069.     self inline: false. "Not now -- maybe later"
  29070.     "Compute the pixel boundaries."
  29071.     firstPixel _ self aaFirstPixelFrom: leftX to: rightX.
  29072.     lastPixel _ self aaLastPixelFrom: leftX to: rightX.
  29073.     aaLevel _ self aaLevelGet.
  29074.     baseShift _ self aaShiftGet.
  29075.     x _ leftX.
  29076.  
  29077.     "Part a: Deal with the first n sub-pixels"
  29078.     x < firstPixel ifTrue:[
  29079.         pv32 _ (pixelValue32 bitAnd: self aaColorMaskGet) >> self aaColorShiftGet.
  29080.         [x < firstPixel] whileTrue:[
  29081.             idx _ x >> baseShift.
  29082.             spanBuffer at: idx put: (spanBuffer at: idx) + pv32.
  29083.             x _ x + 1.
  29084.         ].
  29085.     ].
  29086.  
  29087.     "Part b: Deal with the full pixels"
  29088.     x < lastPixel ifTrue:[
  29089.         colorMask _ (self aaColorMaskGet >> self aaShiftGet) bitOr: 16rF0F0F0F0.
  29090.         pv32 _ (pixelValue32 bitAnd: colorMask) >> self aaShiftGet.
  29091.         [x < lastPixel] whileTrue:[
  29092.             idx _ x >> baseShift.
  29093.             spanBuffer at: idx put: (spanBuffer at: idx) + pv32.
  29094.             x _ x + aaLevel.
  29095.         ].
  29096.     ].
  29097.  
  29098.     "Part c: Deal with the last n sub-pixels"
  29099.     x < rightX ifTrue:[
  29100.         pv32 _ (pixelValue32 bitAnd: self aaColorMaskGet) >> self aaColorShiftGet.
  29101.         [x < rightX] whileTrue:[
  29102.             idx _ x >> baseShift.
  29103.             spanBuffer at: idx put: (spanBuffer at: idx) + pv32.
  29104.             x _ x + 1.
  29105.         ].
  29106.     ].! !
  29107.  
  29108. !BalloonEngineBase methodsFor: 'displaying' stamp: 'ar 11/15/1998 02:04'!
  29109. fillSpan: fill from: leftX to: rightX
  29110.     "Fill the span buffer from leftX to rightX with the given fill.
  29111.     Clip before performing any operations. Return true if the fill must
  29112.     be handled by some Smalltalk code."
  29113.     | x0 x1 type |
  29114.     self inline: false.
  29115.     fill = 0 ifTrue:[^false]. "Nothing to do"
  29116.     "Start from spEnd - we must not paint pixels twice at a scan line"
  29117.     leftX < self spanEndAAGet 
  29118.         ifTrue:[x0 _ self spanEndAAGet]
  29119.         ifFalse:[x0 _ leftX].
  29120.     rightX > (self spanSizeGet << self aaShiftGet) 
  29121.         ifTrue:[x1 _ (self spanSizeGet << self aaShiftGet)]
  29122.         ifFalse:[x1 _ rightX].
  29123.  
  29124.     "Clip left and right values"
  29125.     x0 < self fillMinXGet ifTrue:[x0 _ self fillMinXGet].
  29126.     x1 > self fillMaxXGet ifTrue:[x1 _ self fillMaxXGet].
  29127.  
  29128.     "Adjust start and end values of span"
  29129.     x0 < self spanStartGet ifTrue:[self spanStartPut: x0].
  29130.     x1 > self spanEndGet ifTrue:[self spanEndPut: x1].
  29131.     x1 > self spanEndAAGet ifTrue:[self spanEndAAPut: x1].
  29132.  
  29133.     x0 >= x1 ifTrue:[^false]. "Nothing to do"
  29134.  
  29135.     (self isFillColor: fill) ifTrue:[
  29136.         self fillColorSpan: fill from: x0 to: x1.
  29137.     ] ifFalse:[
  29138.         "Store the values for the dispatch"
  29139.         self lastExportedFillPut: fill.
  29140.         self lastExportedLeftXPut: x0.
  29141.         self lastExportedRightXPut: x1.
  29142.         type _ self fillTypeOf: fill.
  29143.         type <= 1 ifTrue:[^true].
  29144.         self dispatchOn: type in: FillTable.
  29145.     ].
  29146.     ^false! !
  29147.  
  29148. !BalloonEngineBase methodsFor: 'displaying' stamp: 'ar 11/25/1998 14:57'!
  29149. fillSpan: fill from: leftX to: rightX max: maxRightX
  29150.     "Fill the span buffer from leftX to rightX with the given fill.
  29151.     Clip before performing any operations. Return true if the fill must
  29152.     be handled by some Smalltalk code."
  29153.     | x0 x1 type |
  29154.     self inline: false.
  29155.     fill = 0 ifTrue:[^false]. "Nothing to do"
  29156.     "Start from spEnd - we must not paint pixels twice at a scan line"
  29157.     leftX < self spanEndAAGet 
  29158.         ifTrue:[x0 _ self spanEndAAGet]
  29159.         ifFalse:[x0 _ leftX].
  29160.     rightX > (self spanSizeGet << self aaShiftGet) 
  29161.         ifTrue:[x1 _ (self spanSizeGet << self aaShiftGet)]
  29162.         ifFalse:[x1 _ rightX].
  29163.  
  29164.     maxRightX < x1 ifTrue:[x1 _ maxRightX].
  29165.  
  29166.     "Clip left and right values"
  29167.     x0 < self fillMinXGet ifTrue:[x0 _ self fillMinXGet].
  29168.     x1 > self fillMaxXGet ifTrue:[x1 _ self fillMaxXGet].
  29169.  
  29170.     "Adjust start and end values of span"
  29171.     x0 < self spanStartGet ifTrue:[self spanStartPut: x0].
  29172.     x1 > self spanEndGet ifTrue:[self spanEndPut: x1].
  29173.     x1 > self spanEndAAGet ifTrue:[self spanEndAAPut: x1].
  29174.  
  29175.     x0 >= x1 ifTrue:[^false]. "Nothing to do"
  29176.  
  29177.     (self isFillColor: fill) ifTrue:[
  29178.         self fillColorSpan: fill from: x0 to: x1.
  29179.     ] ifFalse:[
  29180.         "Store the values for the dispatch"
  29181.         self lastExportedFillPut: fill.
  29182.         self lastExportedLeftXPut: x0.
  29183.         self lastExportedRightXPut: x1.
  29184.         type _ self fillTypeOf: fill.
  29185.         type <= 1 ifTrue:[^true].
  29186.         self dispatchOn: type in: FillTable.
  29187.     ].
  29188.     ^false! !
  29189.  
  29190. !BalloonEngineBase methodsFor: 'displaying' stamp: 'ar 11/8/1998 15:13'!
  29191. postDisplayAction
  29192.     "We have just blitted a scan line to the screen.
  29193.     Do whatever seems to be a good idea here."
  29194.     "Note: In the future we may check the time needed for this scan line and interrupt processing to give the Smalltalk code a chance to run at a certain time."
  29195.  
  29196.     self inline: false.
  29197.  
  29198.     "Check if there is any more work to do."
  29199.     (self getStartGet >= self getUsedGet and:[self aetUsedGet = 0]) ifTrue:[
  29200.         "No more entries to process"
  29201.         self statePut: GEStateCompleted.
  29202.     ].
  29203.     (self currentYGet >= self fillMaxYGet) ifTrue:[
  29204.         "Out of clipping range"
  29205.         self statePut: GEStateCompleted.
  29206.     ].! !
  29207.  
  29208. !BalloonEngineBase methodsFor: 'transforming' stamp: 'ar 11/8/1998 14:26'!
  29209. incrementPoint: point by: delta
  29210.     self var: #point declareC:'int *point'.
  29211.     point at: 0 put: (point at: 0) + delta.
  29212.     point at: 1 put: (point at: 1) + delta.! !
  29213.  
  29214. !BalloonEngineBase methodsFor: 'transforming' stamp: 'ar 9/5/1999 14:13'!
  29215. transformColor: fillIndex
  29216.     | r g b a transform alphaScale |
  29217.     self var: #transform declareC:'float *transform'.
  29218.     self var: #alphaScale declareC:'double alphaScale'.
  29219.     (fillIndex = 0 or:[self isFillColor: fillIndex]) ifFalse:[^fillIndex].
  29220.     b _ fillIndex bitAnd: 255.
  29221.     g _ (fillIndex >> 8) bitAnd: 255.
  29222.     r _ (fillIndex >> 16) bitAnd: 255.
  29223.     a _ (fillIndex >> 24) bitAnd: 255.
  29224.     (self hasColorTransform) ifTrue:[
  29225.         transform _ self colorTransform.
  29226.         alphaScale _ (a * (transform at: 6) + (transform at: 7)) / a.
  29227.         r _ (r * (transform at: 0) + (transform at: 1) * alphaScale) asInteger.
  29228.         g _ (g * (transform at: 2) + (transform at: 3) * alphaScale) asInteger.
  29229.         b _ (b * (transform at: 4) + (transform at: 5) * alphaScale) asInteger.
  29230.         a _ a * alphaScale.
  29231.         r _ r max: 0. r _ r min: 255.
  29232.         g _ g max: 0. g _ g min: 255.
  29233.         b _ b max: 0. b _ b min: 255.
  29234.         a _ a max: 0. a _ a min: 255.
  29235.     ].
  29236.     a < 1 ifTrue:[^0]."ALWAYS return zero for transparent fills"
  29237.     "If alpha is not 255 (or close thereto) then we need to flush the engine before proceeding"
  29238.     (a < 255 and:[self needsFlush]) 
  29239.         ifTrue:[self stopBecauseOf: GErrorNeedFlush].
  29240.     ^b + (g << 8) + (r << 16) + (a << 24)! !
  29241.  
  29242. !BalloonEngineBase methodsFor: 'transforming' stamp: 'ar 11/24/1998 19:47'!
  29243. transformPoint: point
  29244.     "Transform the given point. If haveMatrix is true then use the current transformation."
  29245.     self var:#point declareC:'int *point'.
  29246.     self hasEdgeTransform ifFalse:[
  29247.         "Multiply each component by aaLevel and add a half pixel"
  29248.         point at: 0 put: (point at: 0) + self destOffsetXGet * self aaLevelGet.
  29249.         point at: 1 put: (point at: 1) + self destOffsetYGet * self aaLevelGet.
  29250.     ] ifTrue:[
  29251.         "Note: AA adjustment is done in #transformPoint: for higher accuracy"
  29252.         self transformPoint: point into: point.
  29253.     ].! !
  29254.  
  29255. !BalloonEngineBase methodsFor: 'transforming' stamp: 'ar 11/1/1998 16:59'!
  29256. transformPoint: srcPoint into: dstPoint
  29257.     "Transform srcPoint into dstPoint by using the currently loaded matrix"
  29258.     "Note: This method has been rewritten so that inlining works (e.g., removing
  29259.     the declarations and adding argument coercions at the appropriate points)"
  29260.     self inline: true.
  29261.     self transformPointX: ((self cCoerce: srcPoint to: 'int *') at: 0) asFloat 
  29262.         y: ((self cCoerce: srcPoint to:'int *') at: 1) asFloat
  29263.         into: (self cCoerce: dstPoint to: 'int *')! !
  29264.  
  29265. !BalloonEngineBase methodsFor: 'transforming' stamp: 'ar 11/24/1998 19:25'!
  29266. transformPointX: xValue y: yValue into: dstPoint
  29267.     "Transform srcPoint into dstPoint by using the currently loaded matrix"
  29268.     "Note: This should be rewritten so that inlining works (e.g., removing
  29269.     the declarations and adding argument coercions at the appropriate points)"
  29270.     | x y transform |
  29271.     self inline: true. "Won't help at the moment ;-("
  29272.     self var: #dstPoint declareC:'int *dstPoint'.
  29273.     self var: #xValue declareC: 'double xValue'.
  29274.     self var: #yValue declareC: 'double yValue'.
  29275.     self var: #transform declareC:'float *transform'.
  29276.     transform _ self edgeTransform.
  29277.     x _ ((((transform at: 0) * xValue) +
  29278.         ((transform at: 1) * yValue) +
  29279.         (transform at: 2)) * self aaLevelGet asFloat) asInteger.
  29280.     y _ ((((transform at: 3) * xValue) +
  29281.         ((transform at: 4) * yValue) +
  29282.         (transform at: 5)) * self aaLevelGet asFloat) asInteger.
  29283.     dstPoint at: 0 put: x.
  29284.     dstPoint at: 1 put: y.! !
  29285.  
  29286. !BalloonEngineBase methodsFor: 'transforming' stamp: 'ar 11/24/1998 19:48'!
  29287. transformPoints: n
  29288.     "Transform n (n=1,2,3) points.
  29289.     If haveMatrix is true then the matrix contains the actual transformation."
  29290.     self inline: true.
  29291.     n > 0 ifTrue:[self transformPoint: self point1Get].
  29292.     n > 1 ifTrue:[self transformPoint: self point2Get].
  29293.     n > 2 ifTrue:[self transformPoint: self point3Get].
  29294.     n > 3 ifTrue:[self transformPoint: self point4Get].! !
  29295.  
  29296. !BalloonEngineBase methodsFor: 'transforming' stamp: 'ar 10/25/1999 00:57'!
  29297. transformWidth: w
  29298.     "Transform the given width"
  29299.     | deltaX deltaY dstWidth dstWidth2 |
  29300.     self inline: false.
  29301.     self var: #deltaX declareC:'double deltaX'.
  29302.     self var: #deltaY declareC:'double deltaY'.
  29303.     w = 0 ifTrue:[^0].
  29304.     self point1Get at: 0 put: 0.
  29305.     self point1Get at: 1 put: 0.
  29306.     self point2Get at: 0 put: w * 256.
  29307.     self point2Get at: 1 put: 0.
  29308.     self point3Get at: 0 put: 0.
  29309.     self point3Get at: 1 put: w * 256.
  29310.     self transformPoints: 3.
  29311.     deltaX _ ((self point2Get at: 0) - (self point1Get at: 0)) asFloat.
  29312.     deltaY _ ((self point2Get at: 1) - (self point1Get at: 1)) asFloat.
  29313.     dstWidth _ (((deltaX * deltaX) + (deltaY * deltaY)) sqrt asInteger + 128) // 256.
  29314.     deltaX _ ((self point3Get at: 0) - (self point1Get at: 0)) asFloat.
  29315.     deltaY _ ((self point3Get at: 1) - (self point1Get at: 1)) asFloat.
  29316.     dstWidth2 _ (((deltaX * deltaX) + (deltaY * deltaY)) sqrt asInteger + 128) // 256.
  29317.     dstWidth2 < dstWidth ifTrue:[dstWidth _ dstWidth2].
  29318.     dstWidth = 0
  29319.         ifTrue:[^1]
  29320.         ifFalse:[^dstWidth]! !
  29321.  
  29322. !BalloonEngineBase methodsFor: 'transforming' stamp: 'ar 11/25/1998 21:33'!
  29323. uncheckedTransformColor: fillIndex
  29324.     | r g b a transform |
  29325.     self var: #transform declareC:'float *transform'.
  29326.     (self hasColorTransform) ifFalse:[^fillIndex].
  29327.     b _ fillIndex bitAnd: 255.
  29328.     g _ (fillIndex >> 8) bitAnd: 255.
  29329.     r _ (fillIndex >> 16) bitAnd: 255.
  29330.     a _ (fillIndex >> 24) bitAnd: 255.
  29331.     transform _ self colorTransform.
  29332.     r _ (r * (transform at: 0) + (transform at: 1)) asInteger.
  29333.     g _ (g * (transform at: 2) + (transform at: 3)) asInteger.
  29334.     b _ (b * (transform at: 4) + (transform at: 5)) asInteger.
  29335.     a _ (a * (transform at: 6) + (transform at: 7)) asInteger.
  29336.     r _ r max: 0. r _ r min: 255.
  29337.     g _ g max: 0. g _ g min: 255.
  29338.     b _ b max: 0. b _ b min: 255.
  29339.     a _ a max: 0. a _ a min: 255.
  29340.     a < 16 ifTrue:[^0]."ALWAYS return zero for transparent fills"
  29341.     ^b + (g << 8) + (r << 16) + (a << 24)! !
  29342.  
  29343. !BalloonEngineBase methodsFor: 'other' stamp: 'ar 11/9/1998 02:06'!
  29344. accurateLengthOf: deltaX with: deltaY
  29345.     "Return the accurate length of the vector described by deltaX and deltaY"
  29346.     | length2 |
  29347.     deltaX = 0 ifTrue:[deltaY < 0 ifTrue:[^0-deltaY] ifFalse:[^deltaY]].
  29348.     deltaY = 0 ifTrue:[deltaX < 0 ifTrue:[^0-deltaX] ifFalse:[^deltaX]].
  29349.     length2 _ (deltaX * deltaX) + (deltaY * deltaY).
  29350.     ^self computeSqrt: length2! !
  29351.  
  29352. !BalloonEngineBase methodsFor: 'other' stamp: 'ar 11/7/1998 14:26'!
  29353. computeSqrt: length2
  29354.     length2 < 32 
  29355.         ifTrue:[^self smallSqrtTable at: length2]
  29356.         ifFalse:[^(length2 asFloat sqrt + 0.5) asInteger]! !
  29357.  
  29358. !BalloonEngineBase methodsFor: 'other' stamp: 'ar 11/8/1998 14:33'!
  29359. estimatedLengthOf: deltaX with: deltaY
  29360.     "Estimate the length of the vector described by deltaX and deltaY.
  29361.     This method may be extremely inaccurate - use it only
  29362.     if you know exactly that this doesn't matter. Otherwise
  29363.     use #accurateLengthOf:width:"
  29364.     | absDx absDy |
  29365.     deltaX >= 0 ifTrue:[absDx _ deltaX] ifFalse:[absDx _ 0 - deltaX].
  29366.     deltaY >= 0 ifTrue:[absDy _ deltaY] ifFalse:[absDy _ 0 - deltaY].
  29367.     absDx > absDy 
  29368.         ifTrue:[^absDx + (absDy // 2)]
  29369.         ifFalse:[^absDy + (absDx // 2)]
  29370.  
  29371. ! !
  29372.  
  29373. !BalloonEngineBase methodsFor: 'other' stamp: 'ar 11/24/1998 19:45'!
  29374. initColorTransform
  29375.     | transform |
  29376.     self inline: false.
  29377.     self var: #transform declareC:'float *transform'.
  29378.     transform _ self colorTransform.
  29379.     transform at: 0 put: (self cCoerce: 1.0 to: 'float').
  29380.     transform at: 1 put: (self cCoerce: 0.0 to: 'float').
  29381.     transform at: 2 put: (self cCoerce: 1.0 to: 'float').
  29382.     transform at: 3 put: (self cCoerce: 0.0 to: 'float').
  29383.     transform at: 4 put: (self cCoerce: 1.0 to: 'float').
  29384.     transform at: 5 put: (self cCoerce: 0.0 to: 'float').
  29385.     transform at: 6 put: (self cCoerce: 1.0 to: 'float').
  29386.     transform at: 7 put: (self cCoerce: 0.0 to: 'float').
  29387.     self hasColorTransformPut: 0.! !
  29388.  
  29389. !BalloonEngineBase methodsFor: 'other' stamp: 'ar 11/24/1998 19:45'!
  29390. initEdgeTransform
  29391.     | transform |
  29392.     self inline: false.
  29393.     self var: #transform declareC:'float *transform'.
  29394.     transform _ self edgeTransform.
  29395.     transform at: 0 put: (self cCoerce: 1.0 to: 'float').
  29396.     transform at: 1 put: (self cCoerce: 0.0 to: 'float').
  29397.     transform at: 2 put: (self cCoerce: 0.0 to: 'float').
  29398.     transform at: 3 put: (self cCoerce: 0.0 to: 'float').
  29399.     transform at: 4 put: (self cCoerce: 1.0 to: 'float').
  29400.     transform at: 5 put: (self cCoerce: 0.0 to: 'float').
  29401.     self hasEdgeTransformPut: 0.! !
  29402.  
  29403. !BalloonEngineBase methodsFor: 'other' stamp: 'ar 11/7/1998 14:26'!
  29404. resetGraphicsEngineStats
  29405.     self inline: false.
  29406.     workBuffer at: GWTimeInitializing put: 0.
  29407.     workBuffer at: GWTimeFinishTest put: 0.
  29408.     workBuffer at: GWTimeNextGETEntry put: 0.
  29409.     workBuffer at: GWTimeAddAETEntry put: 0.
  29410.     workBuffer at: GWTimeNextFillEntry put: 0.
  29411.     workBuffer at: GWTimeMergeFill put: 0.
  29412.     workBuffer at: GWTimeDisplaySpan put: 0.
  29413.     workBuffer at: GWTimeNextAETEntry put: 0.
  29414.     workBuffer at: GWTimeChangeAETEntry put: 0.
  29415.  
  29416.     workBuffer at: GWCountInitializing put: 0.
  29417.     workBuffer at: GWCountFinishTest put: 0.
  29418.     workBuffer at: GWCountNextGETEntry put: 0.
  29419.     workBuffer at: GWCountAddAETEntry put: 0.
  29420.     workBuffer at: GWCountNextFillEntry put: 0.
  29421.     workBuffer at: GWCountMergeFill put: 0.
  29422.     workBuffer at: GWCountDisplaySpan put: 0.
  29423.     workBuffer at: GWCountNextAETEntry put: 0.
  29424.     workBuffer at: GWCountChangeAETEntry put: 0.
  29425.  
  29426.     workBuffer at: GWBezierMonotonSubdivisions put: 0.
  29427.     workBuffer at: GWBezierHeightSubdivisions put: 0.
  29428.     workBuffer at: GWBezierOverflowSubdivisions put: 0.
  29429.     workBuffer at: GWBezierLineConversions put: 0.
  29430. ! !
  29431.  
  29432. !BalloonEngineBase methodsFor: 'other' stamp: 'ar 11/7/1998 14:26'!
  29433. setAALevel: level
  29434.     "Set the anti-aliasing level. Three levels are supported:
  29435.         1 - No antialiasing
  29436.         2 - 2x2 unweighted anti-aliasing
  29437.         4 - 4x4 unweighted anti-aliasing.
  29438.     "
  29439.     | aaLevel |
  29440.     self inline: false.
  29441.     level >= 4 ifTrue:[aaLevel _ 4].
  29442.     (level >= 2) & (level < 4) ifTrue:[aaLevel _ 2].
  29443.     level < 2 ifTrue:[aaLevel _ 1].
  29444.     self aaLevelPut: aaLevel.
  29445.     aaLevel = 1 ifTrue:[
  29446.         self aaShiftPut: 0.
  29447.         self aaColorMaskPut: 16rFFFFFFFF.
  29448.         self aaScanMaskPut: 0.
  29449.     ].
  29450.     aaLevel = 2 ifTrue:[
  29451.         self aaShiftPut: 1.
  29452.         self aaColorMaskPut: 16rFCFCFCFC.
  29453.         self aaScanMaskPut: 1.
  29454.     ].
  29455.     aaLevel = 4 ifTrue:[
  29456.         self aaShiftPut: 2.
  29457.         self aaColorMaskPut: 16rF0F0F0F0.
  29458.         self aaScanMaskPut: 3.
  29459.     ].
  29460.     self aaColorShiftPut: self aaShiftGet * 2.
  29461.     self aaHalfPixelPut: self aaShiftGet.
  29462. ! !
  29463.  
  29464. !BalloonEngineBase methodsFor: 'other' stamp: 'ar 11/8/1998 15:25'!
  29465. smallSqrtTable
  29466.     | theTable |
  29467.     self inline: false.
  29468.     self returnTypeC:'int *'.
  29469.     self var: #theTable declareC:'static int theTable[32] = 
  29470.     {0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6}'.
  29471.     ^theTable! !
  29472.  
  29473. !BalloonEngineBase methodsFor: 'other' stamp: 'ar 11/8/1998 20:57'!
  29474. squaredLengthOf: deltaX with: deltaY
  29475.     ^(deltaX * deltaX) + (deltaY * deltaY)! !
  29476.  
  29477. !BalloonEngineBase methodsFor: 'other' stamp: 'ar 11/25/1998 02:22'!
  29478. stopBecauseOf: stopReason
  29479.     self stopReasonPut: stopReason.
  29480.     engineStopped _ true.! !
  29481.  
  29482. !BalloonEngineBase methodsFor: 'private' stamp: 'ar 5/16/2000 17:09'!
  29483. copyBitsFrom: x0 to: x1 at: yValue
  29484.     copyBitsFn = 0 ifTrue:[
  29485.         "We need copyBits here so try to load it implicitly"
  29486.         self initialiseModule ifFalse:[^false].
  29487.     ].
  29488.     ^self cCode:' ((int (*) (int, int, int)) copyBitsFn)(x0, x1, yValue)'! !
  29489.  
  29490. !BalloonEngineBase methodsFor: 'private' stamp: 'ar 5/13/2000 14:55'!
  29491. errorWrongIndex
  29492.     "Ignore dispatch errors when translating to C
  29493.     (since we have no entry point for #error in the VM proxy)"
  29494.     self cCode:'' inSmalltalk:[self error:'BalloonEngine: Fatal dispatch error']! !
  29495.  
  29496. !BalloonEngineBase methodsFor: 'private' stamp: 'ar 5/16/2000 17:08'!
  29497. loadBitBltFrom: bbObj
  29498.     loadBBFn = 0 ifTrue:[
  29499.         "We need copyBits here so try to load it implicitly"
  29500.         self initialiseModule ifFalse:[^false].
  29501.     ].
  29502.     ^self cCode: '((int (*) (int))loadBBFn)(bbObj)'! !
  29503.  
  29504. !BalloonEngineBase methodsFor: 'private' stamp: 'ar 10/28/1998 20:58'!
  29505. makeUnsignedFrom: someIntegerValue
  29506.     ^someIntegerValue! !
  29507.  
  29508. !BalloonEngineBase methodsFor: 'initialize-release' stamp: 'ar 5/16/2000 19:56'!
  29509. initialiseModule
  29510.     self export: true.
  29511.     loadBBFn _ interpreterProxy ioLoadFunction: 'loadBitBltFrom' From: bbPluginName.
  29512.     copyBitsFn _ interpreterProxy ioLoadFunction: 'copyBitsFromtoat' From: bbPluginName.
  29513.     ^(loadBBFn ~= 0 and:[copyBitsFn ~= 0])! !
  29514.  
  29515. !BalloonEngineBase methodsFor: 'initialize-release' stamp: 'ar 5/16/2000 19:57'!
  29516. moduleUnloaded: aModuleName
  29517.     "The module with the given name was just unloaded.
  29518.     Make sure we have no dangling references."
  29519.     self export: true.
  29520.     self var: #aModuleName type: 'char *'.
  29521.     (aModuleName strcmp: bbPluginName) = 0 ifTrue:[
  29522.         "BitBlt just shut down. How nasty."
  29523.         loadBBFn _ 0.
  29524.         copyBitsFn _ 0.
  29525.     ].! !
  29526.  
  29527. !BalloonEngineBase class methodsFor: 'class initialization' stamp: 'ar 5/16/2000 20:03'!
  29528. declareCVarsIn: cg
  29529.     "Buffers"
  29530.     cg var: #workBuffer type: #'int*'.
  29531.     cg var: #objBuffer type: #'int*'.
  29532.     cg var: #getBuffer type: #'int*'.
  29533.     cg var: #aetBuffer type: #'int*'.
  29534.     cg var: #spanBuffer type: #'unsigned int*'.
  29535.     cg var: #edgeTransform declareC: 'float edgeTransform[6]'.
  29536.     cg var: #doProfileStats declareC: 'int doProfileStats = 0'.
  29537.     cg var: 'bbPluginName' declareC:'char bbPluginName[256] = "BitBltPlugin"'.
  29538. ! !
  29539.  
  29540. !BalloonEngineBase class methodsFor: 'class initialization' stamp: 'ar 11/7/1998 22:26'!
  29541. initialize
  29542.     "BalloonEngineBase initialize"
  29543.     "BalloonEnginePlugin translateDoInlining: true."
  29544.     EdgeInitTable _ self initializeEdgeInitTable.
  29545.     EdgeStepTable _ self initializeEdgeStepTable.
  29546.     WideLineWidthTable _ self initializeWideLineWidthTable.
  29547.     WideLineFillTable _ self initializeWideLineFillTable.
  29548.     FillTable _ self initializeFillTable.! !
  29549.  
  29550. !BalloonEngineBase class methodsFor: 'class initialization' stamp: 'ar 11/4/1998 21:52'!
  29551. initializeEdgeInitTable
  29552.     "BalloonEngineBase initialize"
  29553.     ^#(
  29554.         errorWrongIndex
  29555.         errorWrongIndex
  29556.         errorWrongIndex
  29557.         errorWrongIndex
  29558.  
  29559.         stepToFirstLine
  29560.         stepToFirstWideLine
  29561.         stepToFirstBezier
  29562.         stepToFirstWideBezier
  29563.     )! !
  29564.  
  29565. !BalloonEngineBase class methodsFor: 'class initialization' stamp: 'ar 11/4/1998 21:52'!
  29566. initializeEdgeStepTable
  29567.     "BalloonEngineBase initialize"
  29568.     ^#(
  29569.         errorWrongIndex
  29570.         errorWrongIndex
  29571.         errorWrongIndex
  29572.         errorWrongIndex
  29573.  
  29574.         stepToNextLine
  29575.         stepToNextWideLine
  29576.         stepToNextBezier
  29577.         stepToNextWideBezier
  29578.     )! !
  29579.  
  29580. !BalloonEngineBase class methodsFor: 'class initialization' stamp: 'ar 11/25/1998 19:46'!
  29581. initializeFillTable
  29582.     "BalloonEngineBase initialize"
  29583.     ^#(
  29584.         errorWrongIndex "Type zero - undefined"
  29585.         errorWrongIndex "Type one - external fill"
  29586.  
  29587.         fillLinearGradient "Linear gradient fill"
  29588.         fillRadialGradient "Radial gradient fill"
  29589.  
  29590.         fillBitmapSpan    "Clipped bitmap fill"
  29591.         fillBitmapSpan    "Repeated bitmap fill"
  29592.     )! !
  29593.  
  29594. !BalloonEngineBase class methodsFor: 'class initialization' stamp: 'ar 11/4/1998 23:03'!
  29595. initializeWideLineFillTable
  29596.     "BalloonEngineBase initialize"
  29597.     ^#(
  29598.         errorWrongIndex
  29599.         errorWrongIndex
  29600.         returnWideLineFill
  29601.         returnWideBezierFill
  29602.     )! !
  29603.  
  29604. !BalloonEngineBase class methodsFor: 'class initialization' stamp: 'ar 11/4/1998 23:03'!
  29605. initializeWideLineWidthTable
  29606.     "BalloonEngineBase initialize"
  29607.     ^#(
  29608.         errorWrongIndex
  29609.         errorWrongIndex
  29610.         returnWideLineWidth
  29611.         returnWideBezierWidth
  29612.     )! !
  29613.  
  29614. !BalloonEngineBase class methodsFor: 'accessing' stamp: 'ar 5/11/2000 23:48'!
  29615. moduleName
  29616.     ^'B2DPlugin'! !
  29617.  
  29618. !BalloonEngineBase class methodsFor: 'accessing' stamp: 'ar 11/11/1998 21:56'!
  29619. simulatorClass
  29620.     ^BalloonEngineSimulation! !
  29621.  
  29622. !BalloonEngineBase class methodsFor: 'documentation' stamp: 'ar 11/7/1998 03:33'!
  29623. a1EngineOutline
  29624.     "The following is a brief outline on how the engine works.
  29625.  
  29626.     In general, we're using a pretty straight-forward active edge approach, e.g., 
  29627.     we classify all edges into three different states:
  29628.         a) Waiting for processing
  29629.         b) Active (e.g., being processed)
  29630.         c) Finished
  29631.     Before the engine starts all edges are sorted by their y-value in a so-called
  29632.     'global edge table' (furthermore referred to as GET) and processed in top 
  29633.     to bottom order (the edges are also sorted by x-value but this is only for 
  29634.     simplifying the insertion when adding edges).
  29635.  
  29636.     Then, we start at the first visible scan line and execute the following steps:
  29637.  
  29638.     1) Move all edges starting at the current scan line from state a) to state b)
  29639.  
  29640.     This step requires the GET to be sorted so that we only need to check
  29641.     the first edges of the GET. After the initial state of the edge (e.g., it's current
  29642.     pixel value and data required for incremental updates) the edges are then 
  29643.     inserted in the 'active edge table' (called AET). The sort order in the AET is 
  29644.     defined by the pixel position of each edge at the current scan line and thus 
  29645.     edges are kept in increasing x-order.
  29646.  
  29647.     This step does occur for every edge only once and is therefore not the most
  29648.     time-critical part of the approach.
  29649.  
  29650.     2) Draw the current scan line
  29651.  
  29652.     This step includes two sub-parts. In the first part, the scan line is assembled.
  29653.     This involves walking through the AET and drawing the pixels between
  29654.     each two neighbour edges. Since each edge can have two associated fills
  29655.     (a 'left' and a 'right' fill) we need to make sure that edges falling on the
  29656.     same pixel position do not affect the painted image. This issue is discussed
  29657.     in the aetScanningProblems documentation.
  29658.  
  29659.     Wide edges (e.g., edges having an associated width) are also handled during
  29660.     this step. Wide edges are always preferred over interior fills - this ensures
  29661.     that the outline of an object cannot be overdrawn by any interior fill of
  29662.     a shape that ends very close to the edge (for more information see wideEdges 
  29663.     documentation).
  29664.  
  29665.     After the scan is assembled it is blitted to the screen. This only happens all
  29666.     'aaLevel' scan lines (for further information see the antiAliasing documentation).
  29667.  
  29668.     This second step is done at each scan line in the image, and is usually the most
  29669.     time-critical part.
  29670.  
  29671.     3) Update all currently active edges
  29672.  
  29673.     Updating the active edges basically means either to remove the edge from the AET
  29674.     (if it is at the end y value) or incrementally computing the pixel value for the
  29675.     next scan line. Based on the information gathered in the first step, this part
  29676.     should be executed as fast as possible - it happens for each edge in the AET
  29677.     at each scan line and may be the bottleneck if many edges are involved in
  29678.     the drawing operations (see the TODO list; part of it probably deals with the
  29679.     issue).
  29680.  
  29681. "
  29682.     ^self error:'Comment only'! !
  29683.  
  29684. !BalloonEngineBase class methodsFor: 'documentation' stamp: 'ar 11/7/1998 03:55'!
  29685. a2AntiAliasing
  29686.     "The engine currently used a very simple, but efficient anti-aliasing scheme. It is based on a square unweighted filter of size 1, 2, or 4 resulting in three levels of anti-aliasing:
  29687.  
  29688.     * No anti-aliasing (filter size 1)
  29689.     This simply draws each pixel 'as is' on the screen
  29690.  
  29691.     * Slight anti-aliasing (filter size 2)
  29692.     Doubles the rasterization size in each direction and assembles the pixel value as the medium of the four sub-pixels falling into the full pixel
  29693.  
  29694.     * Full anti-aliasing (filter size 4)
  29695.     Quadruples the rasterization in each direction and assembles the pixel value as the medium of the sixteen sub-pixels falling into the full pixel
  29696.  
  29697.  
  29698. The reason for using these three AA levels is simply efficiency of computing. Since the above filters (1x1, 2x2, 4x4) have all power of two elements (1, 4, and 16) we can compute the weighted sum of the final pixel by computing
  29699.  
  29700.     destColor _ destColor + (srcColor // subPixels)
  29701.  
  29702. And, since we're only working on 32bit destination buffer we do not need to compute the components of each color separately but can neatly put the entire color into a single formula:
  29703.  
  29704.     destPixel32 _ destPixel32 + ((srcPixel32 bitAnd: aaMask) >> aaShift).
  29705.  
  29706. with aaMask = 16rFFFFFFFF for aaLevel = 1, aaMask = 16rFCFCFCFC for aaLevel = 2, aaMask = 16rF0F0F0F0 for aaLevel = 4 and aaShift = 0, 2, or 4 for the different levels. However, while the above is efficient to compute, it also drops accuracy. So, for the 4x4 anti-aliasing we're effectively only using the high 4 bits of each color component. While is generally not a problem (we add 16 sub-pixels into this value) there is a simple arithmetic difficulty because the above cannot fill the entire range of values, e.g.,
  29707.  
  29708.     16 * (255 // 16) = 16 * 15 = 240
  29709.  
  29710. and not 255 as expected. We solve this problem by replicating the top n (n=0, 2, 4) bits of each component as the low bits in an adjustment step before blitting to scan line to the screen. This has the nice effect that a zero pixel value (e.g., transparent) will remain zero, a white pixel (as computed above) will result in a value of 255 for each component (defining opaque white) and each color inbetween linearly mapped between 0 and 255. 
  29711.  
  29712. "
  29713.     ^self error:'Comment only'! !
  29714.  
  29715. !BalloonEngineBase class methodsFor: 'documentation' stamp: 'ar 11/7/1998 03:35'!
  29716. a3RasterizationRules
  29717.  
  29718.  
  29719.     ^self error:'Comment only'! !
  29720.  
  29721. !BalloonEngineBase class methodsFor: 'documentation' stamp: 'ar 11/7/1998 03:35'!
  29722. a4WideEdges! !
  29723.  
  29724. !BalloonEngineBase class methodsFor: 'documentation' stamp: 'ar 11/7/1998 03:36'!
  29725. a5AETScanningProblems
  29726.     "Due to having two fill entries (one left and one right) there can be problems while scanning the active edge table. In general, the AET should look like the following (ri - regions, ei - edges, fi - fills):
  29727.  
  29728.             |                \                |
  29729.     r1        |        r2         \        r3        |        r4
  29730.             |                  \                |
  29731.             e1                 e2                e3        
  29732.  
  29733.     with:
  29734.         f(r1) = fLeft(e1) = 0                (empty fill, denoted -)
  29735.         f(r2) = fRight(e1) = fLeft(e2)        (denoted x)
  29736.         f(r3) = fRight(e2) = fLeft(e3)    (denoted o)
  29737.         f(r4) = fRight(e3) = 0
  29738.  
  29739.     However, due to integer arithmetic used during computations the AET may look like the following:
  29740.             X
  29741.             \|                        |
  29742.              | \                        |
  29743.              |   \                    |
  29744.     r1         | r2 \            r3        |        r4
  29745.              |       \                    |
  29746.             e1        e2                e3        
  29747.  
  29748.     In this case, the starting point of e1 and e2 have the same x value at the first scan line but e2 has been sorted before e1 (Note: This can happen in *many* cases - the above is just a very simple example). Given the above outlined fill relations we have a problem. So, for instance, using the left/right fills as defined by the edges would lead to the effect that in the first scan line region r3 is actually filled with the right fill of e1 while it should actually be filled with the right fill of e2. This leads to noticable artifacts in the image and increasing resolution does not help.
  29749.  
  29750.     What we do here is defining an arbitrary sort order between fills (you can think of it as a depth value but the only thing that matters is that you can order the fills by this number and that the empty fill is always sorted at the end), and toggle the fills between an 'active' and an 'inactive' state at each edge. This is done as follows:
  29751.     For each edge ei in the AET do:
  29752.         * if fLeft(ei) isActive then removeActive(fLeft(ei)) else addActive(fLeft(ei))
  29753.         * if fRight(ei) isActive then removeActive(fRight(ei)) else addActive(fRight(ei))
  29754.         * draw the span from ei to ei+1 with currentActive
  29755.     where addActive adds the fill to the list of currently active fills, removeActive() removes the fill from the active list and currentActive returns the fill AS DEFINED BY THE SORT ORDER from the list of active fills. Note that this does not change anything in the first example above because the list will only contain one entry (besides the empty fill). In the second case however, it will lead to the following sequence:
  29756.  
  29757.     * toggle fLeft(e2) = f(r2) = 'x'
  29758.         - makes fLeft(e2) active
  29759.         - activeList = 'x'
  29760.     * toggle fRight(e2) = f(r3) = 'o'
  29761.         - makes fRight(e2) active
  29762.         - activeList = 'xo'
  29763.     * draw span from e2 to e1
  29764.         Depending on the sort order between 'x' and 'o' the region will be drawn with either one of the fills. It is significant to note here that the occurence of such a problem is generally only *very* few pixels large (in the above example zero pixels) and will therefore not be visually noticable. In any case, there is a unique decision for the fill to use here and that is what we need if the problem did not happen accidentally (e.g., someone has manually changed one fill of an edge but not the fill of the opposite edge).
  29765.  
  29766.     * toggle fLeft(e1) = f(r1) = '-'
  29767.         - makes fLeft(r1) visible
  29768.         - activeList = 'xo-'
  29769.         [Note: empty fills are a special case. 
  29770.         They can be ignored since they sort last
  29771.         and the activeList can return the empty
  29772.         fill if it is itself empty].
  29773.     * toggle fRight(e1) = f(r2) = 'x'
  29774.         - makes fRight(e1) invisible
  29775.         - activeList = 'o-'
  29776.     * draw span from e2 to e3
  29777.         Since the active list contains (besides the empty fill) only one fill value this will be used. Fortunately, this is the correct fill because it is the fill we had initially defined for the region r2.
  29778.  
  29779. An interesting side effect of the above is that there is no such notion as a 'left' or 'right' fill anymore. Another (not-so-nice) side effect is that the entire AET has to be scanned from the beginning even if only the last few edges actually affect the visible region.
  29780.  
  29781. PS. I need to find a way of clipping the edges for this. More on it later...
  29782. "
  29783.     ^self error:'Comment only'! !
  29784.  
  29785. !BalloonEngineBase class methodsFor: 'documentation' stamp: 'ar 11/8/1998 00:06'!
  29786. a6StuffTODO
  29787.     "This is an unordered list of things to do:
  29788.  
  29789. BalloonEnginePlugin>>stepToFirstBezierIn:at:
  29790.     1)    Check if reducing maxSteps from 2*deltaY to deltaY 
  29791.         brings a *significant* performance improvement.
  29792.         In theory this should make for double step performance
  29793.         but will cost in quality. Might be that the AA stuff will
  29794.         compensate for this - but I'm not really sure.
  29795.  
  29796. BalloonEngineBase>>dispatchOn:in:
  29797.     1)    Check what dispatches cost most and must be inlined
  29798.         by an #inlinedDispatchOn:in: Probably this will be
  29799.         stepping and eventually wide line stuff but we'll see.
  29800.  
  29801. BalloonEngineBase
  29802.     1)    Check which variables should become inst vars, if any.
  29803.         This will remove an indirection during memory access
  29804.         and might allow a couple of optimizations by the C compiler.
  29805.  
  29806. Anti-Aliasing:
  29807.     1)    Check if we can use a weighted 3x3 filter function of the form
  29808.                 1    2    1
  29809.                 2    4    2
  29810.                 1    2    1
  29811.         Which should be *extremely* nice for fonts (it's sharpening
  29812.         edges). The good thing about the above is that it sums up to
  29813.         16 (as in the 4x4 case) but I don't know how to keep a history
  29814.         without needing two extra scan lines.
  29815.  
  29816.     2)    Check if we can - somehow - integrate more general filters.
  29817.  
  29818.     3) Unroll the loops during AA so we can copy and mask aaLevel pixels
  29819.        in each step between start and end. This should speed up filling
  29820.        by a factor of 2-4 (in particular for difficult stuff like radial gradients).
  29821.  
  29822. Clipping
  29823.     1)    Find a way of clipping edges left of the clip rectangle
  29824.         or at least ignoring most of them after the first scan line.
  29825.         The AET scanning problems discuss the issue but it should be
  29826.         possible to keep the color list between spans (if not empty)
  29827.         and speed up drawing at the very right (such as in the
  29828.         Winnie Pooh example where a lot of stuff is between the
  29829.         left border and the clipping rect.
  29830.  
  29831.     2)    Check if we can determine empty states of the color list and
  29832.         an edge that is longer than anything left of it. This should
  29833.         work in theory but might be relatively expensive to compute.
  29834.  
  29835. "
  29836.     ^self error:'Comment only'! !
  29837.  
  29838. !BalloonEngineBase class methodsFor: 'pool initialization' stamp: 'ar 11/24/1998 23:54'!
  29839. initEdgeConstants: dict
  29840.     "Initialize the edge constants"
  29841.     self initFromSpecArray:
  29842.     #(
  29843.         "Edge primitive types"
  29844.         (GEPrimitiveEdge 2)            "External edge - not handled by the GE"
  29845.         (GEPrimitiveWideEdge 3)        "Wide external edge"
  29846.         (GEPrimitiveLine 4)            "Straight line"
  29847.         (GEPrimitiveWideLine 5)        "Wide line"
  29848.         (GEPrimitiveBezier 6)        "Quadratic bezier curve"
  29849.         (GEPrimitiveWideBezier 7)    "Wide bezier curve"
  29850.  
  29851.         "Special flags"
  29852.         (GEPrimitiveWide 16r01)        "Flag determining a wide primitive"
  29853.         (GEPrimitiveWideMask 16rFE)    "Mask for clearing the wide flag"
  29854.         (GEEdgeFillsInvalid 16r10000) "Flag determining if left/right fills of an edge are invalid"
  29855.         (GEEdgeClipFlag 16r20000)    "Flag determining if this is a clip edge"
  29856.  
  29857.         "General edge state constants"
  29858.         (GEXValue 4)                    "Current raster x"
  29859.         (GEYValue 5)                    "Current raster y"
  29860.         (GEZValue 6)                    "Current raster z"
  29861.         (GENumLines 7)                    "Number of scan lines remaining"
  29862.         (GEFillIndexLeft 8)                "Left fill index"
  29863.         (GEFillIndexRight 9)                "Right fill index"
  29864.         (GEBaseEdgeSize 10)                "Basic size of each edge"
  29865.  
  29866.         "General fill state constants"
  29867.         (GEBaseFillSize 4)                "Basic size of each fill"
  29868.  
  29869.         "General Line state constants"
  29870.         (GLXDirection 10)                "Direction of edge (1: left-to-right; -1: right-to-left)"
  29871.         (GLYDirection 11)                "Direction of edge (1: top-to-bottom; -1: bottom-to-top)"
  29872.         (GLXIncrement 12)                "Increment at each scan line"
  29873.         (GLError 13)                        "Current error"
  29874.         (GLErrorAdjUp 14)                "Error to add at each scan line"
  29875.         (GLErrorAdjDown 15)                "Error to subtract on roll-over"
  29876.             "Note: The following entries are only needed before the incremental
  29877.             state is computed. They are therefore aliased to the error values above"
  29878.         (GLEndX 14)                        "End X of line"
  29879.         (GLEndY 15)                        "End Y of line"
  29880.         (GLBaseSize 16)                    "Basic size of each line"
  29881.  
  29882.         "Additional stuff for wide lines"
  29883.         (GLWideFill 16)                    "Current fill of line"
  29884.         (GLWideWidth 17)                "Current width of line"
  29885.         (GLWideEntry 18)                "Initial steps"
  29886.         (GLWideExit 19)                    "Final steps"
  29887.         (GLWideExtent 20)                "Target width"
  29888.         (GLWideSize 21)                    "Size of wide lines"
  29889.  
  29890.         "General Bezier state constants"
  29891.         (GBUpdateData 10)                "Incremental update data for beziers"
  29892.             (GBUpdateX 0)                "Last computed X value (24.8)"
  29893.             (GBUpdateY 1)                "Last computed Y value (24.8)"
  29894.             (GBUpdateDX 2)                "Delta X forward difference step (8.24)"
  29895.             (GBUpdateDY 3)                "Delta Y forward difference step (8.24)"
  29896.             (GBUpdateDDX 4)                "Delta DX forward difference step (8.24)"
  29897.             (GBUpdateDDY 5)                "Delta DY forward difference step (8.24)"
  29898.         "Note: The following four entries are only needed before the incremental
  29899.             state is computed. They are therefore aliased to the incremental values above"
  29900.         (GBViaX 12)                        "via x"
  29901.         (GBViaY 13)                        "via y"
  29902.         (GBEndX 14)                        "end x"
  29903.         (GBEndY 15)                        "end y"
  29904.         (GBBaseSize 16)                    "Basic size of each bezier.
  29905.                                         Note: MUST be greater or equal to the size of lines"
  29906.         "Additional stuff for wide beziers"
  29907.         (GBWideFill 16)                    "Current fill of line"
  29908.         (GBWideWidth 17)                "Current width of line"
  29909.         (GBWideEntry 18)                "Initial steps"
  29910.         (GBWideExit 19)                    "Final steps"
  29911.         (GBWideExtent 20)                "Target extent"
  29912.         (GBFinalX 21)                    "Final X value"
  29913.         (GBWideUpdateData 22)    "Update data for second curve"
  29914.         (GBWideSize 28)                    "Size of wide beziers"
  29915.  
  29916.     ) in: dict.! !
  29917.  
  29918. !BalloonEngineBase class methodsFor: 'pool initialization' stamp: 'ar 11/27/1998 14:19'!
  29919. initFillConstants: dict
  29920.     "Initialize the fill constants"
  29921.     "BalloonEngineBase initPool"
  29922.     self initFromSpecArray:
  29923.     #(
  29924.         "Fill primitive types"
  29925.         (GEPrimitiveFill 16r100)
  29926.         (GEPrimitiveLinearGradientFill 16r200)
  29927.         (GEPrimitiveRadialGradientFill 16r300)
  29928.         (GEPrimitiveClippedBitmapFill 16r400)
  29929.         (GEPrimitiveRepeatedBitmapFill 16r500)
  29930.  
  29931.         "General fill state constants"
  29932.         (GEBaseFillSize 4)                "Basic size of each fill"
  29933.  
  29934.         "Oriented fill constants"
  29935.         (GFOriginX 4)                "X origin of fill"
  29936.         (GFOriginY 5)                "Y origin of fill"
  29937.         (GFDirectionX 6)                "X direction of fill"
  29938.         (GFDirectionY 7)                "Y direction of fill"
  29939.         (GFNormalX 8)                "X normal of fill"
  29940.         (GFNormalY 9)                "Y normal of fill"
  29941.  
  29942.         "Gradient fill constants"
  29943.         (GFRampLength 10)            "Length of following color ramp"
  29944.         (GFRampOffset 12)            "Offset of first ramp entry"
  29945.         (GGBaseSize 12)
  29946.  
  29947.         "Bitmap fill constants"
  29948.         (GBBitmapWidth 10)            "Width of bitmap"
  29949.         (GBBitmapHeight 11)            "Height of bitmap"
  29950.         (GBBitmapDepth 12)            "Depth of bitmap"
  29951.         (GBBitmapSize 13)            "Size of bitmap words"
  29952.         (GBBitmapRaster 14)            "Size of raster line"
  29953.         (GBColormapSize 15)            "Size of colormap, if any"
  29954.         (GBTileFlag 16)                "True if the bitmap is tiled"
  29955.         (GBColormapOffset 18)        "Offset of colormap, if any"
  29956.         (GBMBaseSize 18)            "Basic size of bitmap fill"
  29957.     ) in: dict.! !
  29958.  
  29959. !BalloonEngineBase class methodsFor: 'pool initialization' stamp: 'ar 11/11/1998 22:26'!
  29960. initFromSpecArray: specArray in: aDictionary
  29961.     specArray do:[:spec|
  29962.         self initPoolVariable: spec first value: spec last in: aDictionary.
  29963.     ]! !
  29964.  
  29965. !BalloonEngineBase class methodsFor: 'pool initialization' stamp: 'ar 11/11/1998 22:27'!
  29966. initPool
  29967.     "BalloonEngineBase initPool"
  29968.     (Smalltalk includesKey: #BalloonEngineConstants) ifFalse:[
  29969.         Smalltalk declare: #BalloonEngineConstants from: Undeclared.
  29970.     ].
  29971.     (Smalltalk at: #BalloonEngineConstants) isNil ifTrue:[
  29972.         (Smalltalk associationAt: #BalloonEngineConstants) value: Dictionary new.
  29973.     ].
  29974.     self initPool: (Smalltalk at: #BalloonEngineConstants).! !
  29975.  
  29976. !BalloonEngineBase class methodsFor: 'pool initialization' stamp: 'ar 11/11/1998 22:27'!
  29977. initPool: aDictionary
  29978.     self initStateConstants: aDictionary.
  29979.     self initWorkBufferConstants: aDictionary.
  29980.     self initPrimitiveConstants: aDictionary.
  29981.     self initEdgeConstants: aDictionary.
  29982.     self initFillConstants: aDictionary.
  29983.     self initializeInstVarNames: BalloonEngine in: aDictionary prefixedBy: 'BE'.
  29984.     self initializeInstVarNames: BalloonEdgeData in: aDictionary prefixedBy: 'ET'.
  29985.     self initializeInstVarNames: BalloonFillData in: aDictionary prefixedBy: 'FT'.! !
  29986.  
  29987. !BalloonEngineBase class methodsFor: 'pool initialization' stamp: 'ar 11/11/1998 22:27'!
  29988. initPoolFull    "BalloonEngineBase initPoolFull"
  29989.     "Move old stuff to Undeclared and re-initialize the receiver"
  29990.     BalloonEngineConstants associationsDo:[:assoc|
  29991.         Undeclared declare: assoc key from: BalloonEngineConstants.
  29992.     ].
  29993.     self initPool.
  29994.     Undeclared removeUnreferencedKeys.! !
  29995.  
  29996. !BalloonEngineBase class methodsFor: 'pool initialization' stamp: 'ar 11/11/1998 22:27'!
  29997. initPoolVariable: token value: value in: aDictionary
  29998.     aDictionary declare: token from: Undeclared.
  29999.     (aDictionary associationAt: token) value: value.! !
  30000.  
  30001. !BalloonEngineBase class methodsFor: 'pool initialization' stamp: 'ar 11/11/1998 22:27'!
  30002. initPrimitiveConstants: dict
  30003.     "Initialize the primitive constants"
  30004.     self initFromSpecArray:
  30005.     #(
  30006.         "Primitive type constants"
  30007.         (GEPrimitiveUnknown 0)
  30008.         (GEPrimitiveEdgeMask 16rFF)
  30009.         (GEPrimitiveFillMask 16rFF00)
  30010.         (GEPrimitiveTypeMask 16rFFFF)
  30011.  
  30012.         "General state constants (Note: could be compressed later)"
  30013.         (GEObjectType 0)                "Type of object"
  30014.         (GEObjectLength 1)            "Length of object"
  30015.         (GEObjectIndex 2)            "Index into external objects"
  30016.         (GEObjectUnused 3)            "Currently unused"
  30017.  
  30018.     ) in: dict.! !
  30019.  
  30020. !BalloonEngineBase class methodsFor: 'pool initialization' stamp: 'ar 11/25/1998 00:25'!
  30021. initStateConstants: dict
  30022.     "Initialize the state Constants"
  30023.     "BalloonEngineBase initPool"
  30024.     self initFromSpecArray:
  30025.     #(
  30026.         (GEStateUnlocked 0)            "Buffer is unlocked and can be modified as wanted"
  30027.         (GEStateAddingFromGET 1)    "Adding edges from the GET"
  30028.         (GEStateWaitingForEdge 2)    "Waiting for edges added to GET"
  30029.         (GEStateScanningAET 3)        "Scanning the active edge table"
  30030.         (GEStateWaitingForFill 4)        "Waiting for a fill to mix in during AET scan"
  30031.         (GEStateBlitBuffer 5)            "Blt the current scan line"
  30032.         (GEStateUpdateEdges 6)        "Update edges to next scan line"
  30033.         (GEStateWaitingChange 7)    "Waiting for a changed edge"
  30034.         (GEStateCompleted 8)            "Rendering completed"
  30035.  
  30036.         "Error constants"
  30037.         (GErrorNoMoreSpace 1)        "No more space in collection"
  30038.         (GErrorBadState 2)            "Tried to call a primitive while engine in bad state"
  30039.         (GErrorNeedFlush 3)            "Tried to call a primitive that requires flushing before"
  30040.  
  30041.         "Incremental error constants"
  30042.         (GErrorGETEntry 4)            "Unknown entry in GET"
  30043.         (GErrorFillEntry 5)            "Unknown FILL encountered"
  30044.         (GErrorAETEntry 6)            "Unknown entry in AET"
  30045.     ) in: dict.! !
  30046.  
  30047. !BalloonEngineBase class methodsFor: 'pool initialization' stamp: 'ar 11/25/1998 00:20'!
  30048. initWorkBufferConstants: dict
  30049.     "Initialize the work buffer constants"
  30050.     "BalloonEngineBase initPool"
  30051.     self initFromSpecArray:
  30052.     #(
  30053.         "General work buffer constants"
  30054.         (GWMagicNumber 16r416E6469)    "Magic number"
  30055.         (GWHeaderSize 128)                "Size of header"
  30056.         (GWMinimalSize 256)                "Minimal size of work buffer"
  30057.  
  30058.         "Header entries"
  30059.         (GWMagicIndex 0)                "Index of magic number"
  30060.         (GWSize 1)                        "Size of full buffer"
  30061.         (GWState 2)                        "Current state (e.g., locked or not)"
  30062.         "Buffer entries"
  30063.         (GWObjStart 8)                    "objStart"
  30064.         (GWObjUsed 9)                    "objUsed"
  30065.         (GWBufferTop 10)                "wbTop"
  30066.         (GWGETStart 11)                    "getStart"
  30067.         (GWGETUsed 12)                    "getUsed"
  30068.         (GWAETStart 13)                    "aetStart"
  30069.         (GWAETUsed 14)                    "aetUsed"
  30070.  
  30071.         "Transform entries"
  30072.         (GWHasEdgeTransform 16)        "True if we have an edge transformation"
  30073.         (GWHasColorTransform 17)        "True if we have a color transformation"
  30074.         (GWEdgeTransform 18)            "2x3 edge transformation"
  30075.         (GWColorTransform 24)            "8 word RGBA color transformation"
  30076.  
  30077.         "Span entries"
  30078.         (GWSpanStart 32)                "spStart"
  30079.         (GWSpanSize 33)                    "spSize"
  30080.         (GWSpanEnd 34)                    "spEnd"
  30081.         (GWSpanEndAA 35)                "spEndAA"
  30082.  
  30083.         "Bounds entries"
  30084.         (GWFillMinX 36)                    "fillMinX"
  30085.         (GWFillMaxX 37)                    "fillMaxX"
  30086.         (GWFillMinY 38)                    "fillMinY"
  30087.         (GWFillMaxY 39)                    "fillMaxY"
  30088.         (GWFillOffsetX 40)                "fillOffsetX"
  30089.         (GWFillOffsetY 41)                "fillOffsetY"
  30090.         (GWClipMinX 42)
  30091.         (GWClipMaxX 43)
  30092.         (GWClipMinY 44)
  30093.         (GWClipMaxY 45)
  30094.         (GWDestOffsetX 46)
  30095.         (GWDestOffsetY 47)
  30096.  
  30097.         "AA entries"
  30098.         (GWAALevel 48)                    "aaLevel"
  30099.         (GWAAShift 49)                    "aaShift"
  30100.         (GWAAColorShift 50)                "aaColorShift"
  30101.         (GWAAColorMask 51)                "aaColorMask"
  30102.         (GWAAScanMask 52)                "aaScanMask"
  30103.         (GWAAHalfPixel 53)                "aaHalfPixel"
  30104.  
  30105.         "Misc entries"
  30106.         (GWNeedsFlush 63)                "True if the engine may need a flush"
  30107.         (GWStopReason 64)                "stopReason"
  30108.         (GWLastExportedEdge 65)            "last exported edge"
  30109.         (GWLastExportedFill 66)            "last exported fill"
  30110.         (GWLastExportedLeftX 67)            "last exported leftX"
  30111.         (GWLastExportedRightX 68)        "last exported rightX"
  30112.         (GWClearSpanBuffer 69)            "Do we have to clear the span buffer?"
  30113.         (GWPointListFirst 70)                "First point list in buffer"
  30114.  
  30115.         (GWPoint1 80)
  30116.         (GWPoint2 82)
  30117.         (GWPoint3 84)
  30118.         (GWPoint4 86)
  30119.  
  30120.         (GWCurrentY 88)
  30121.  
  30122.         "Profile stats"
  30123.         (GWTimeInitializing 90)
  30124.         (GWCountInitializing 91)
  30125.         (GWTimeFinishTest 92)
  30126.         (GWCountFinishTest 93)
  30127.         (GWTimeNextGETEntry 94)
  30128.         (GWCountNextGETEntry 95)
  30129.         (GWTimeAddAETEntry 96)
  30130.         (GWCountAddAETEntry 97)
  30131.         (GWTimeNextFillEntry 98)
  30132.         (GWCountNextFillEntry 99)
  30133.         (GWTimeMergeFill 100)
  30134.         (GWCountMergeFill 101)
  30135.         (GWTimeDisplaySpan 102)
  30136.         (GWCountDisplaySpan 103)
  30137.         (GWTimeNextAETEntry 104)
  30138.         (GWCountNextAETEntry 105)
  30139.         (GWTimeChangeAETEntry 106)
  30140.         (GWCountChangeAETEntry 107)
  30141.  
  30142.         "Bezier stats"
  30143.         (GWBezierMonotonSubdivisions 108)     "# of subdivision due to non-monoton beziers"
  30144.         (GWBezierHeightSubdivisions 109)        "# of subdivisions due to excessive height"
  30145.         (GWBezierOverflowSubdivisions 110)    "# of subdivisions due to possible int overflow"
  30146.         (GWBezierLineConversions 111)        "# of beziers converted to lines"
  30147.  
  30148.         (GWHasClipShapes 112)        "True if the engine contains clip shapes"
  30149.         (GWCurrentZ 113)            "Current z value of primitives"
  30150.     ) in: dict.! !
  30151.  
  30152. !BalloonEngineBase class methodsFor: 'pool initialization' stamp: 'ar 11/11/1998 22:27'!
  30153. initializeInstVarNames: aClass in: aDictionary prefixedBy: aString
  30154.  
  30155.     | token value |
  30156.     aClass instVarNames doWithIndex:[:instVarName :index|
  30157.         token _ (aString, instVarName first asUppercase asString, (instVarName copyFrom: 2 to: instVarName size),'Index') asSymbol.
  30158.         value _ index - 1.
  30159.         aDictionary declare: token from: Undeclared.
  30160.         (aDictionary associationAt: token) value: value.
  30161.     ].
  30162.     token _ (aString, aClass name,'Size') asSymbol.
  30163.     aDictionary declare:  token from: Undeclared.
  30164.     (aDictionary associationAt: token) value: aClass instSize.! !
  30165.  
  30166. !BalloonEnginePlugin methodsFor: 'primitives' stamp: 'ar 5/11/2000 23:07'!
  30167. primitiveAddBezier
  30168.     | leftFill rightFill viaOop endOop startOop nSegments |
  30169.     self export: true.
  30170.     self inline: false.
  30171.  
  30172.     "Fail if we have the wrong number of arguments"
  30173.     interpreterProxy methodArgumentCount = 5 
  30174.         ifFalse:[^interpreterProxy primitiveFail].
  30175.  
  30176.     rightFill _ interpreterProxy positive32BitValueOf: (interpreterProxy stackValue: 0).
  30177.     leftFill _ interpreterProxy positive32BitValueOf: (interpreterProxy stackValue: 1).
  30178.     viaOop _ interpreterProxy stackObjectValue: 2.
  30179.     endOop _ interpreterProxy stackObjectValue: 3.
  30180.     startOop _ interpreterProxy stackObjectValue: 4.
  30181.     interpreterProxy failed ifTrue:[^nil].
  30182.  
  30183.     (self quickLoadEngineFrom: (interpreterProxy stackObjectValue: 5) requiredState: GEStateUnlocked)
  30184.         ifFalse:[^interpreterProxy primitiveFail].
  30185.  
  30186.     "Make sure the fills are okay"
  30187.     ((self isFillOkay: leftFill) and:[self isFillOkay: rightFill])
  30188.             ifFalse:[^interpreterProxy primitiveFail].
  30189.  
  30190.     "Do a quick check if the fillIndices are equal - if so, just ignore it"
  30191.     leftFill = rightFill & false ifTrue:[
  30192.         ^interpreterProxy pop: 6. "Leave rcvr on stack"
  30193.     ].
  30194.  
  30195.  
  30196.     self loadPoint: self point1Get from: startOop.
  30197.     self loadPoint: self point2Get from: viaOop.
  30198.     self loadPoint: self point3Get from: endOop.
  30199.     interpreterProxy failed ifTrue:[^0].
  30200.  
  30201.     self transformPoints: 3.
  30202.  
  30203.     nSegments _ self loadAndSubdivideBezierFrom: self point1Get 
  30204.                         via: self point2Get 
  30205.                         to: self point3Get 
  30206.                         isWide: false.
  30207.     self needAvailableSpace: nSegments * GBBaseSize.
  30208.     engineStopped ifFalse:[
  30209.         leftFill _ self transformColor: leftFill.
  30210.         rightFill _ self transformColor: rightFill].
  30211.     engineStopped ifFalse:[
  30212.         self loadWideBezier: 0 lineFill: 0 leftFill: leftFill rightFill: rightFill n: nSegments.
  30213.     ].
  30214.     engineStopped ifTrue:[
  30215.         "Make sure the stack is okay"
  30216.         self wbStackClear.
  30217.         ^interpreterProxy primitiveFail].
  30218.  
  30219.     interpreterProxy failed ifFalse:[
  30220.         self storeEngineStateInto: engine.
  30221.         interpreterProxy pop: 5. "Leave rcvr on stack"
  30222.     ].! !
  30223.  
  30224. !BalloonEnginePlugin methodsFor: 'primitives' stamp: 'ar 5/11/2000 23:08'!
  30225. primitiveAddBezierShape
  30226.     | points lineFill lineWidth fillIndex length isArray segSize nSegments |
  30227.     self export: true.
  30228.     self inline: false.
  30229.  
  30230.     "Fail if we have the wrong number of arguments"
  30231.     interpreterProxy methodArgumentCount = 5 
  30232.         ifFalse:[^interpreterProxy primitiveFail].
  30233.  
  30234.     lineFill _ interpreterProxy positive32BitValueOf: (interpreterProxy stackValue: 0).
  30235.     lineWidth _ interpreterProxy stackIntegerValue: 1.
  30236.     fillIndex _ interpreterProxy positive32BitValueOf: (interpreterProxy stackValue: 2).
  30237.     nSegments _ interpreterProxy stackIntegerValue: 3.
  30238.     points _ interpreterProxy stackObjectValue: 4.
  30239.     interpreterProxy failed ifTrue:[^nil].
  30240.  
  30241.     (self quickLoadEngineFrom: (interpreterProxy stackObjectValue: 5) requiredState: GEStateUnlocked)
  30242.         ifFalse:[^interpreterProxy primitiveFail].
  30243.  
  30244.     "First, do a check if the points look okay"
  30245.     length _ interpreterProxy slotSizeOf: points.
  30246.     (interpreterProxy isWords: points) ifTrue:[
  30247.         isArray _ false.
  30248.         "Either PointArray or ShortPointArray"
  30249.         (length = (nSegments * 3) or:[length = (nSegments * 6)])
  30250.             ifFalse:[^interpreterProxy primitiveFail].
  30251.     ] ifFalse:["Must be Array of points"
  30252.         (interpreterProxy fetchClassOf: points) = interpreterProxy classArray
  30253.             ifFalse:[^interpreterProxy primitiveFail].
  30254.         length = (nSegments * 3)
  30255.             ifFalse:[^interpreterProxy primitiveFail].
  30256.         isArray _ true.
  30257.     ].
  30258.  
  30259.     "Now check that we have some hope to have enough free space.
  30260.     Do this by assuming nPoints boundaries of maximum size,
  30261.     hoping that most of the fills will be colors and many boundaries
  30262.     will be line segments"
  30263.  
  30264.     (lineWidth = 0 or:[lineFill = 0])
  30265.         ifTrue:[segSize _ GLBaseSize]
  30266.         ifFalse:[segSize _ GLWideSize].
  30267.     (self needAvailableSpace: segSize * nSegments)
  30268.         ifFalse:[^interpreterProxy primitiveFail].
  30269.  
  30270.     "Check the fills"
  30271.     ((self isFillOkay: lineFill) and:[self isFillOkay: fillIndex])
  30272.         ifFalse:[^interpreterProxy primitiveFail]. 
  30273.  
  30274.     "Transform colors"
  30275.     lineFill _ self transformColor: lineFill.
  30276.     fillIndex _ self transformColor: fillIndex.
  30277.     engineStopped ifTrue:[^interpreterProxy primitiveFail].
  30278.  
  30279.     "Check if have anything at all to do"
  30280.     ((lineFill = 0 or:[lineWidth = 0]) and:[fillIndex = 0])
  30281.         ifTrue:[^interpreterProxy pop: 5].
  30282.  
  30283.     "Transform the lineWidth"
  30284.     lineWidth = 0 ifFalse:[
  30285.         lineWidth _ self transformWidth: lineWidth.
  30286.         lineWidth < 1 ifTrue:[lineWidth _ 1]].
  30287.  
  30288.     "And load the actual shape"
  30289.     isArray ifTrue:[
  30290.         self loadArrayShape: points nSegments: nSegments
  30291.             fill: fillIndex lineWidth: lineWidth lineFill: lineFill.
  30292.     ] ifFalse:[
  30293.         self loadShape: (interpreterProxy firstIndexableField: points) nSegments: nSegments
  30294.             fill: fillIndex lineWidth: lineWidth lineFill: lineFill 
  30295.             pointsShort: (nSegments * 3 = length)].
  30296.  
  30297.     engineStopped ifTrue:[^interpreterProxy primitiveFail].
  30298.  
  30299.     interpreterProxy failed ifFalse:[
  30300.         self needsFlushPut: 1.
  30301.         self storeEngineStateInto: engine.
  30302.         interpreterProxy pop: 5. "Leave rcvr on stack"
  30303.     ].! !
  30304.  
  30305. !BalloonEnginePlugin methodsFor: 'primitives' stamp: 'ar 5/11/2000 23:10'!
  30306. primitiveAddBitmapFill
  30307.  
  30308.     | nrmOop dirOop originOop tileFlag fill xIndex cmOop formOop |
  30309.     self export: true.
  30310.     self inline: false.
  30311.  
  30312.     "Fail if we have the wrong number of arguments"
  30313.     interpreterProxy methodArgumentCount = 7 
  30314.         ifFalse:[^interpreterProxy primitiveFail].
  30315.  
  30316.     xIndex _ interpreterProxy stackIntegerValue: 0.
  30317.     xIndex <= 0 ifTrue:[^interpreterProxy primitiveFail].
  30318.     nrmOop _ interpreterProxy stackObjectValue: 1.
  30319.     dirOop _ interpreterProxy stackObjectValue: 2.
  30320.     originOop _ interpreterProxy stackObjectValue: 3.
  30321.     tileFlag _ interpreterProxy booleanValueOf: (interpreterProxy stackValue: 4).
  30322.     tileFlag ifTrue:[tileFlag _ 1] ifFalse:[tileFlag _ 0].
  30323.     cmOop _ interpreterProxy stackObjectValue: 5.
  30324.     formOop _ interpreterProxy stackObjectValue: 6.
  30325.     interpreterProxy failed ifTrue:[^nil].
  30326.  
  30327.     (self quickLoadEngineFrom: (interpreterProxy stackObjectValue: 7) requiredState: GEStateUnlocked)
  30328.         ifFalse:[^interpreterProxy primitiveFail].
  30329.  
  30330.     self loadPoint: self point1Get from: originOop.
  30331.     self loadPoint: self point2Get from: dirOop.
  30332.     self loadPoint: self point3Get from: nrmOop.
  30333.     interpreterProxy failed ifTrue:[^0].
  30334.  
  30335.     fill _ self loadBitmapFill: formOop 
  30336.                 colormap: cmOop
  30337.                 tile: tileFlag
  30338.                 from: self point1Get 
  30339.                 along: self point2Get 
  30340.                 normal: self point3Get 
  30341.                 xIndex: xIndex-1.
  30342.     engineStopped ifTrue:[
  30343.         "Make sure the stack is okay"
  30344.         ^interpreterProxy primitiveFail].
  30345.  
  30346.     interpreterProxy failed ifFalse:[
  30347.         self storeEngineStateInto: engine.
  30348.         interpreterProxy pop: 8.
  30349.         interpreterProxy push: (interpreterProxy positive32BitIntegerFor: fill).
  30350.     ].! !
  30351.  
  30352. !BalloonEnginePlugin methodsFor: 'primitives' stamp: 'ar 5/11/2000 23:06'!
  30353. primitiveAddCompressedShape
  30354.     | fillIndexList lineFills lineWidths rightFills leftFills nSegments points pointsShort |
  30355.     self export: true.
  30356.     self inline: false.
  30357.  
  30358.     "Fail if we have the wrong number of arguments"
  30359.     interpreterProxy methodArgumentCount = 7 
  30360.         ifFalse:[^interpreterProxy primitiveFail].
  30361.  
  30362.     fillIndexList _ interpreterProxy stackObjectValue: 0.
  30363.     lineFills _ interpreterProxy stackObjectValue: 1.
  30364.     lineWidths _ interpreterProxy stackObjectValue: 2.
  30365.     rightFills _ interpreterProxy stackObjectValue: 3.
  30366.     leftFills _ interpreterProxy stackObjectValue: 4.
  30367.     nSegments _ interpreterProxy stackIntegerValue: 5.
  30368.     points _ interpreterProxy stackObjectValue: 6.
  30369.     interpreterProxy failed ifTrue:[^nil].
  30370.  
  30371.     (self quickLoadEngineFrom: (interpreterProxy stackObjectValue: 7) requiredState: GEStateUnlocked)
  30372.         ifFalse:[^interpreterProxy primitiveFail].
  30373.  
  30374.     "First, do a check if the compressed shape is okay"
  30375.     (self checkCompressedShape: points 
  30376.             segments: nSegments 
  30377.             leftFills: leftFills 
  30378.             rightFills: rightFills 
  30379.             lineWidths: lineWidths 
  30380.             lineFills: lineFills 
  30381.             fillIndexList: fillIndexList) ifFalse:[^interpreterProxy primitiveFail].
  30382.  
  30383.     "Now check that we have some hope to have enough free space.
  30384.     Do this by assuming nSegments boundaries of maximum size,
  30385.     hoping that most of the fills will be colors and many boundaries
  30386.     will be line segments"
  30387.  
  30388.     (self needAvailableSpace: (GBBaseSize max: GLBaseSize) * nSegments)
  30389.         ifFalse:[^interpreterProxy primitiveFail].
  30390.  
  30391.     "Check if the points are short"
  30392.     pointsShort _ (interpreterProxy slotSizeOf: points) = (nSegments * 3).
  30393.  
  30394.     "Then actually load the compressed shape"
  30395.     self loadCompressedShape: (interpreterProxy firstIndexableField: points)
  30396.             segments: nSegments 
  30397.             leftFills: (interpreterProxy firstIndexableField: leftFills)
  30398.             rightFills: (interpreterProxy firstIndexableField: rightFills)
  30399.             lineWidths: (interpreterProxy firstIndexableField: lineWidths)
  30400.             lineFills: (interpreterProxy firstIndexableField: lineFills)
  30401.             fillIndexList: (interpreterProxy firstIndexableField: fillIndexList)
  30402.             pointShort: pointsShort.
  30403.  
  30404.     engineStopped ifTrue:[^interpreterProxy primitiveFail].
  30405.  
  30406.     interpreterProxy failed ifFalse:[
  30407.         self needsFlushPut: 1.
  30408.         self storeEngineStateInto: engine.
  30409.         interpreterProxy pop: 7. "Leave rcvr on stack"
  30410.     ].! !
  30411.  
  30412. !BalloonEnginePlugin methodsFor: 'primitives' stamp: 'ar 5/11/2000 23:13'!
  30413. primitiveAddGradientFill
  30414.  
  30415.     | isRadial nrmOop dirOop originOop rampOop fill |
  30416.     self export: true.
  30417.     self inline: false.
  30418.  
  30419.     "Fail if we have the wrong number of arguments"
  30420.     interpreterProxy methodArgumentCount = 5 
  30421.         ifFalse:[^interpreterProxy primitiveFail].
  30422.  
  30423.     isRadial _ interpreterProxy booleanValueOf: (interpreterProxy stackValue: 0).
  30424.     nrmOop _ interpreterProxy stackValue: 1.
  30425.     dirOop _ interpreterProxy stackValue: 2.
  30426.     originOop _ interpreterProxy stackValue: 3.
  30427.     rampOop _ interpreterProxy stackValue: 4.
  30428.     interpreterProxy failed ifTrue:[^nil].
  30429.  
  30430.     (self quickLoadEngineFrom: (interpreterProxy stackObjectValue: 5) requiredState: GEStateUnlocked)
  30431.         ifFalse:[^interpreterProxy primitiveFail].
  30432.  
  30433.     self loadPoint: self point1Get from: originOop.
  30434.     self loadPoint: self point2Get from: dirOop.
  30435.     self loadPoint: self point3Get from: nrmOop.
  30436.     interpreterProxy failed ifTrue:[^0].
  30437.  
  30438.     fill _ self loadGradientFill: rampOop 
  30439.                 from: self point1Get 
  30440.                 along: self point2Get 
  30441.                 normal: self point3Get 
  30442.                 isRadial: isRadial.
  30443.     engineStopped ifTrue:[
  30444.         "Make sure the stack is okay"
  30445.         ^interpreterProxy primitiveFail].
  30446.  
  30447.     interpreterProxy failed ifFalse:[
  30448.         self storeEngineStateInto: engine.
  30449.         interpreterProxy pop: 6.
  30450.         interpreterProxy push: (interpreterProxy positive32BitIntegerFor: fill).
  30451.     ].! !
  30452.  
  30453. !BalloonEnginePlugin methodsFor: 'primitives' stamp: 'ar 5/11/2000 23:08'!
  30454. primitiveAddLine
  30455.     | leftFill rightFill endOop startOop |
  30456.     self export: true.
  30457.     self inline: false.
  30458.  
  30459.     "Fail if we have the wrong number of arguments"
  30460.     interpreterProxy methodArgumentCount = 4 
  30461.         ifFalse:[^interpreterProxy primitiveFail].
  30462.  
  30463.     rightFill _ interpreterProxy positive32BitValueOf: (interpreterProxy stackValue: 0).
  30464.     leftFill _ interpreterProxy positive32BitValueOf: (interpreterProxy stackValue: 1).
  30465.     endOop _ interpreterProxy stackObjectValue: 2.
  30466.     startOop _ interpreterProxy stackO